From 0fcb8a18597f4c8470935b2fa0c039271b108bbf Mon Sep 17 00:00:00 2001 From: Bagus <25834188+contactjavas@users.noreply.github.com> Date: Wed, 8 Feb 2023 22:12:35 +0700 Subject: [PATCH] rename composer vedor dir & kirki packages dir --- .gitattributes | 8 +- build.sh | 4 +- composer.json | 102 +- {vendor => kirki-composer}/autoload.php | 2 +- kirki-composer/bin/phpcbf | 120 + kirki-composer/bin/phpcbf.bat | 5 + kirki-composer/bin/phpcs | 120 + kirki-composer/bin/phpcs.bat | 5 + .../composer/ClassLoader.php | 0 .../composer/InstalledVersions.php | 0 {vendor => kirki-composer}/composer/LICENSE | 0 .../composer/autoload_classmap.php | 0 .../composer/autoload_namespaces.php | 0 kirki-composer/composer/autoload_psr4.php | 18 + .../composer/autoload_real.php | 8 +- kirki-composer/composer/autoload_static.php | 125 + .../composer/include_paths.php | 0 .../composer/installed.json | 0 .../composer/installed.php | 0 .../workflows/continuous-integration.yml | 62 + .../installers/.github/workflows/lint.yml | 30 + .../installers/.github/workflows/phpstan.yml | 49 + kirki-composer/composer/installers/LICENSE | 19 + .../composer/installers/composer.json | 116 + .../composer/installers/phpstan.neon.dist | 12 + .../src/Composer/Installers/AglInstaller.php | 29 + .../Installers/AkauntingInstaller.php | 23 + .../Installers/AnnotateCmsInstaller.php | 13 + .../Composer/Installers/AsgardInstaller.php | 58 + .../Composer/Installers/AttogramInstaller.php | 11 + .../src/Composer/Installers/BaseInstaller.php | 137 + .../Composer/Installers/BitrixInstaller.php | 123 + .../Composer/Installers/BonefishInstaller.php | 11 + .../Composer/Installers/CakePHPInstaller.php | 67 + .../src/Composer/Installers/ChefInstaller.php | 12 + .../Composer/Installers/CiviCrmInstaller.php | 11 + .../Installers/ClanCatsFrameworkInstaller.php | 12 + .../Composer/Installers/CockpitInstaller.php | 36 + .../Installers/CodeIgniterInstaller.php | 13 + .../Installers/Concrete5Installer.php | 15 + .../Composer/Installers/CroogoInstaller.php | 23 + .../Composer/Installers/DecibelInstaller.php | 12 + .../Composer/Installers/DframeInstaller.php | 11 + .../Composer/Installers/DokuWikiInstaller.php | 57 + .../Composer/Installers/DolibarrInstaller.php | 18 + .../Composer/Installers/DrupalInstaller.php | 24 + .../src/Composer/Installers/ElggInstaller.php | 11 + .../Composer/Installers/EliasisInstaller.php | 14 + .../Installers/ExpressionEngineInstaller.php | 31 + .../Installers/EzPlatformInstaller.php | 12 + .../src/Composer/Installers/FuelInstaller.php | 13 + .../Composer/Installers/FuelphpInstaller.php | 11 + .../src/Composer/Installers/GravInstaller.php | 29 + .../Composer/Installers/HuradInstaller.php | 27 + .../Composer/Installers/ImageCMSInstaller.php | 13 + .../src/Composer/Installers/Installer.php | 280 ++ .../src/Composer/Installers/ItopInstaller.php | 11 + .../Composer/Installers/KanboardInstaller.php | 20 + .../Composer/Installers/KnownInstaller.php | 13 + .../Composer/Installers/KodiCMSInstaller.php | 12 + .../Composer/Installers/KohanaInstaller.php | 11 + .../LanManagementSystemInstaller.php | 27 + .../Composer/Installers/LaravelInstaller.php | 11 + .../Composer/Installers/LavaLiteInstaller.php | 12 + .../Composer/Installers/LithiumInstaller.php | 12 + .../Installers/MODULEWorkInstaller.php | 11 + .../Composer/Installers/MODXEvoInstaller.php | 18 + .../Composer/Installers/MagentoInstaller.php | 13 + .../Composer/Installers/MajimaInstaller.php | 46 + .../src/Composer/Installers/MakoInstaller.php | 11 + .../Composer/Installers/MantisBTInstaller.php | 25 + .../Composer/Installers/MatomoInstaller.php | 28 + .../Composer/Installers/MauticInstaller.php | 43 + .../src/Composer/Installers/MayaInstaller.php | 38 + .../Installers/MediaWikiInstaller.php | 58 + .../Composer/Installers/MiaoxingInstaller.php | 11 + .../Installers/MicroweberInstaller.php | 145 + .../src/Composer/Installers/ModxInstaller.php | 14 + .../Composer/Installers/MoodleInstaller.php | 67 + .../Composer/Installers/OctoberInstaller.php | 57 + .../Composer/Installers/OntoWikiInstaller.php | 26 + .../Composer/Installers/OsclassInstaller.php | 14 + .../src/Composer/Installers/OxidInstaller.php | 49 + .../src/Composer/Installers/PPIInstaller.php | 11 + .../Composer/Installers/PantheonInstaller.php | 12 + .../Composer/Installers/PhiftyInstaller.php | 13 + .../Composer/Installers/PhpBBInstaller.php | 13 + .../Composer/Installers/PiwikInstaller.php | 28 + .../Installers/PlentymarketsInstaller.php | 28 + .../src/Composer/Installers/Plugin.php | 28 + .../Composer/Installers/PortoInstaller.php | 11 + .../Installers/PrestashopInstaller.php | 12 + .../Installers/ProcessWireInstaller.php | 23 + .../Composer/Installers/PuppetInstaller.php | 12 + .../Composer/Installers/PxcmsInstaller.php | 62 + .../Composer/Installers/RadPHPInstaller.php | 26 + .../Composer/Installers/ReIndexInstaller.php | 12 + .../Composer/Installers/Redaxo5Installer.php | 12 + .../Composer/Installers/RedaxoInstaller.php | 12 + .../Installers/RoundcubeInstaller.php | 21 + .../src/Composer/Installers/SMFInstaller.php | 12 + .../Composer/Installers/ShopwareInstaller.php | 66 + .../Installers/SilverStripeInstaller.php | 33 + .../Installers/SiteDirectInstaller.php | 34 + .../Composer/Installers/StarbugInstaller.php | 14 + .../Composer/Installers/SyDESInstaller.php | 55 + .../Composer/Installers/SyliusInstaller.php | 11 + .../src/Composer/Installers/TaoInstaller.php | 32 + .../Installers/TastyIgniterInstaller.php | 85 + .../Composer/Installers/TheliaInstaller.php | 14 + .../src/Composer/Installers/TuskInstaller.php | 17 + .../Installers/UserFrostingInstaller.php | 11 + .../Composer/Installers/VanillaInstaller.php | 12 + .../Composer/Installers/VgmcpInstaller.php | 59 + .../Composer/Installers/WHMCSInstaller.php | 22 + .../Composer/Installers/WinterInstaller.php | 71 + .../Composer/Installers/WolfCMSInstaller.php | 11 + .../Installers/WordPressInstaller.php | 14 + .../Composer/Installers/YawikInstaller.php | 23 + .../src/Composer/Installers/ZendInstaller.php | 13 + .../Composer/Installers/ZikulaInstaller.php | 12 + .../composer/installers/src/bootstrap.php | 18 + .../composer/platform_check.php | 0 .../LICENSE.md | 22 + .../README.md | 285 ++ .../composer.json | 71 + .../src/Plugin.php | 637 +++ .../php-compatibility/CHANGELOG.md | 1488 +++++++ .../php-compatibility/LICENSE | 165 + .../php-compatibility/PHPCSAliases.php | 73 + .../AbstractComplexVersionSniff.php | 147 + .../AbstractFunctionCallParameterSniff.php | 193 + .../AbstractNewFeatureSniff.php | 115 + .../AbstractRemovedFeatureSniff.php | 156 + .../ComplexVersionInterface.php | 84 + .../PHPCompatibility/PHPCSHelper.php | 678 +++ .../PHPCompatibility/Sniff.php | 2267 ++++++++++ .../ForbiddenAbstractPrivateMethodsSniff.php | 90 + .../Classes/NewAnonymousClassesSniff.php | 91 + .../Sniffs/Classes/NewClassesSniff.php | 913 ++++ .../Classes/NewConstVisibilitySniff.php | 80 + .../Classes/NewLateStaticBindingSniff.php | 88 + .../Classes/NewTypedPropertiesSniff.php | 132 + .../Classes/RemovedOrphanedParentSniff.php | 115 + .../Sniffs/Constants/NewConstantsSniff.php | 3756 +++++++++++++++++ .../Constants/NewMagicClassConstantSniff.php | 80 + .../Constants/RemovedConstantsSniff.php | 574 +++ .../DiscouragedSwitchContinueSniff.php | 238 ++ ...ForbiddenBreakContinueOutsideLoopSniff.php | 116 + ...denBreakContinueVariableArgumentsSniff.php | 110 + ...enSwitchWithMultipleDefaultBlocksSniff.php | 81 + .../NewExecutionDirectivesSniff.php | 378 ++ .../NewForeachExpressionReferencingSniff.php | 99 + .../NewListInForeachSniff.php | 84 + .../ControlStructures/NewMultiCatchSniff.php | 78 + .../Extensions/RemovedExtensionsSniff.php | 346 ++ ...biddenParameterShadowSuperGlobalsSniff.php | 79 + .../ForbiddenParametersWithSameNameSniff.php | 88 + .../ForbiddenToStringParametersSniff.php | 99 + ...orbiddenVariableNamesInClosureUseSniff.php | 122 + .../FunctionDeclarations/NewClosureSniff.php | 264 ++ .../NewExceptionsFromToStringSniff.php | 171 + .../NewNullableTypesSniff.php | 169 + .../NewParamTypeDeclarationsSniff.php | 237 ++ .../NewReturnTypeDeclarationsSniff.php | 194 + .../NonStaticMagicMethodsSniff.php | 216 + .../NewMagicMethodsSniff.php | 231 + .../RemovedMagicAutoloadSniff.php | 92 + .../RemovedNamespacedAssertSniff.php | 101 + .../RemovedPHP4StyleConstructorsSniff.php | 158 + .../ReservedFunctionNamesSniff.php | 205 + ...gumentFunctionsReportCurrentValueSniff.php | 455 ++ .../ArgumentFunctionsUsageSniff.php | 169 + .../NewFunctionParametersSniff.php | 1109 +++++ .../Sniffs/FunctionUse/NewFunctionsSniff.php | 2008 +++++++++ ...ionalToRequiredFunctionParametersSniff.php | 173 + .../RemovedFunctionParametersSniff.php | 292 ++ .../FunctionUse/RemovedFunctionsSniff.php | 1104 +++++ ...uiredToOptionalFunctionParametersSniff.php | 350 ++ .../Generators/NewGeneratorReturnSniff.php | 158 + .../IniDirectives/NewIniDirectivesSniff.php | 855 ++++ .../RemovedIniDirectivesSniff.php | 424 ++ .../NewConstantArraysUsingConstSniff.php | 82 + .../NewConstantArraysUsingDefineSniff.php | 101 + .../NewConstantScalarExpressionsSniff.php | 556 +++ .../Sniffs/InitialValue/NewHeredocSniff.php | 100 + .../Interfaces/InternalInterfacesSniff.php | 103 + .../Sniffs/Interfaces/NewInterfacesSniff.php | 362 ++ .../Keywords/CaseSensitiveKeywordsSniff.php | 76 + .../ForbiddenNamesAsDeclaredSniff.php | 259 ++ .../ForbiddenNamesAsInvokedFunctionsSniff.php | 188 + .../Sniffs/Keywords/ForbiddenNamesSniff.php | 442 ++ .../Sniffs/Keywords/NewKeywordsSniff.php | 391 ++ .../NewEmptyNonVariableSniff.php | 91 + .../NewLanguageConstructsSniff.php | 159 + .../Sniffs/Lists/AssignmentOrderSniff.php | 188 + .../ForbiddenEmptyListAssignmentSniff.php | 116 + .../Sniffs/Lists/NewKeyedListSniff.php | 227 + .../Lists/NewListReferenceAssignmentSniff.php | 74 + .../Sniffs/Lists/NewShortListSniff.php | 84 + .../ForbiddenToStringParametersSniff.php | 103 + .../MethodUse/NewDirectCallsToCloneSniff.php | 117 + .../Miscellaneous/NewPHPOpenTagEOFSniff.php | 147 + .../RemovedAlternativePHPTagsSniff.php | 172 + .../Miscellaneous/ValidIntegersSniff.php | 250 ++ .../ChangedConcatOperatorPrecedenceSniff.php | 199 + .../ForbiddenNegativeBitshiftSniff.php | 109 + .../Sniffs/Operators/NewOperatorsSniff.php | 317 ++ .../Sniffs/Operators/NewShortTernarySniff.php | 73 + .../RemovedTernaryAssociativitySniff.php | 157 + .../ForbiddenGetClassNullSniff.php | 84 + ...orbiddenStripTagsSelfClosingXHTMLSniff.php | 113 + .../NewArrayReduceInitialTypeSniff.php | 116 + .../ParameterValues/NewFopenModesSniff.php | 119 + .../NewHTMLEntitiesEncodingDefaultSniff.php | 92 + .../NewHashAlgorithmsSniff.php | 185 + .../NewIDNVariantDefaultSniff.php | 91 + .../NewIconvMbstringCharsetDefaultSniff.php | 231 + .../NewNegativeStringOffsetSniff.php | 129 + .../ParameterValues/NewPCREModifiersSniff.php | 127 + .../ParameterValues/NewPackFormatSniff.php | 132 + .../NewPasswordAlgoConstantValuesSniff.php | 125 + .../NewProcOpenCmdArraySniff.php | 136 + .../NewStripTagsAllowableTagsArraySniff.php | 152 + .../RemovedHashAlgorithmsSniff.php | 117 + .../RemovedIconvEncodingSniff.php | 86 + .../RemovedImplodeFlexibleParamOrderSniff.php | 323 ++ ...emovedMbStrrposEncodingThirdParamSniff.php | 149 + .../RemovedMbstringModifiersSniff.php | 135 + .../RemovedNonCryptoHashSniff.php | 121 + .../RemovedPCREModifiersSniff.php | 241 ++ .../RemovedSetlocaleStringSniff.php | 104 + .../ForbiddenCallTimePassByReferenceSniff.php | 259 ++ .../NewArrayStringDereferencingSniff.php | 199 + .../Sniffs/Syntax/NewArrayUnpackingSniff.php | 142 + .../Syntax/NewClassMemberAccessSniff.php | 192 + .../Syntax/NewDynamicAccessToStaticSniff.php | 89 + .../Syntax/NewFlexibleHeredocNowdocSniff.php | 255 ++ .../NewFunctionArrayDereferencingSniff.php | 187 + .../NewFunctionCallTrailingCommaSniff.php | 120 + .../Sniffs/Syntax/NewShortArraySniff.php | 77 + .../RemovedCurlyBraceArrayAccessSniff.php | 362 ++ .../Syntax/RemovedNewReferenceSniff.php | 80 + .../NewUnicodeEscapeSequenceSniff.php | 162 + .../Sniffs/TypeCasts/NewTypeCastsSniff.php | 222 + .../TypeCasts/RemovedTypeCastsSniff.php | 158 + .../Sniffs/Upgrade/LowPHPCSSniff.php | 187 + .../Sniffs/Upgrade/LowPHPSniff.php | 182 + .../NewGroupUseDeclarationsSniff.php | 118 + .../NewUseConstFunctionSniff.php | 109 + .../ForbiddenGlobalVariableVariableSniff.php | 125 + .../ForbiddenThisUseContextsSniff.php | 425 ++ .../NewUniformVariableSyntaxSniff.php | 114 + .../RemovedPredefinedGlobalVariablesSniff.php | 318 ++ .../PHPCompatibility/ruleset.xml | 7 + .../php-compatibility/README.md | 250 ++ .../php-compatibility/composer.json | 44 + .../php-compatibility/phpunit-bootstrap.php | 86 + .../phpcompatibility-paragonie/LICENSE | 165 + .../ruleset.xml | 40 + .../ruleset.xml | 244 ++ .../phpcompatibility-paragonie/README.md | 143 + .../phpcompatibility-paragonie/composer.json | 38 + .../phpcompatibility-wp/LICENSE | 165 + .../PHPCompatibilityWP/ruleset.xml | 82 + .../phpcompatibility-wp/README.md | 135 + .../phpcompatibility-wp/composer.json | 37 + .../squizlabs/php_codesniffer/CONTRIBUTING.md | 13 + .../php_codesniffer/CodeSniffer.conf | 5 + .../php_codesniffer/CodeSniffer.conf.dist | 9 + .../squizlabs/php_codesniffer/README.md | 134 + .../squizlabs/php_codesniffer/autoload.php | 342 ++ .../squizlabs/php_codesniffer/bin/phpcbf | 19 + .../squizlabs/php_codesniffer/bin/phpcbf.bat | 12 + .../squizlabs/php_codesniffer/bin/phpcs | 19 + .../squizlabs/php_codesniffer/bin/phpcs.bat | 12 + .../squizlabs/php_codesniffer/composer.json | 40 + .../squizlabs/php_codesniffer/licence.txt | 24 + .../squizlabs/php_codesniffer/phpcs.xsd | 136 + .../squizlabs/php_codesniffer/src/Config.php | 1704 ++++++++ .../src/Exceptions/DeepExitException.php | 18 + .../src/Exceptions/RuntimeException.php | 15 + .../src/Exceptions/TokenizerException.php | 15 + .../php_codesniffer/src/Files/DummyFile.php | 82 + .../php_codesniffer/src/Files/File.php | 2829 +++++++++++++ .../php_codesniffer/src/Files/FileList.php | 255 ++ .../php_codesniffer/src/Files/LocalFile.php | 219 + .../src/Filters/ExactMatch.php | 108 + .../php_codesniffer/src/Filters/Filter.php | 285 ++ .../src/Filters/GitModified.php | 66 + .../php_codesniffer/src/Filters/GitStaged.php | 68 + .../squizlabs/php_codesniffer/src/Fixer.php | 806 ++++ .../src/Generators/Generator.php | 117 + .../php_codesniffer/src/Generators/HTML.php | 270 ++ .../src/Generators/Markdown.php | 161 + .../php_codesniffer/src/Generators/Text.php | 253 ++ .../php_codesniffer/src/Reporter.php | 423 ++ .../php_codesniffer/src/Reports/Cbf.php | 253 ++ .../src/Reports/Checkstyle.php | 109 + .../php_codesniffer/src/Reports/Code.php | 362 ++ .../php_codesniffer/src/Reports/Csv.php | 91 + .../php_codesniffer/src/Reports/Diff.php | 130 + .../php_codesniffer/src/Reports/Emacs.php | 90 + .../php_codesniffer/src/Reports/Full.php | 231 + .../php_codesniffer/src/Reports/Gitblame.php | 91 + .../php_codesniffer/src/Reports/Hgblame.php | 110 + .../php_codesniffer/src/Reports/Info.php | 172 + .../php_codesniffer/src/Reports/Json.php | 106 + .../php_codesniffer/src/Reports/Junit.php | 131 + .../src/Reports/Notifysend.php | 242 ++ .../php_codesniffer/src/Reports/Report.php | 64 + .../php_codesniffer/src/Reports/Source.php | 336 ++ .../php_codesniffer/src/Reports/Summary.php | 183 + .../php_codesniffer/src/Reports/Svnblame.php | 73 + .../src/Reports/VersionControl.php | 376 ++ .../php_codesniffer/src/Reports/Xml.php | 126 + .../squizlabs/php_codesniffer/src/Ruleset.php | 1383 ++++++ .../squizlabs/php_codesniffer/src/Runner.php | 889 ++++ .../src/Sniffs/AbstractArraySniff.php | 172 + .../src/Sniffs/AbstractPatternSniff.php | 936 ++++ .../src/Sniffs/AbstractScopeSniff.php | 191 + .../src/Sniffs/AbstractVariableSniff.php | 230 + .../php_codesniffer/src/Sniffs/Sniff.php | 80 + .../DisallowLongArraySyntaxStandard.xml | 23 + .../DisallowShortArraySyntaxStandard.xml | 23 + .../Classes/DuplicateClassNameStandard.xml | 27 + .../Classes/OpeningBraceSameLineStandard.xml | 28 + .../AssignmentInConditionStandard.xml | 23 + .../CodeAnalysis/EmptyStatementStandard.xml | 23 + .../ForLoopShouldBeWhileLoopStandard.xml | 23 + .../ForLoopWithTestFunctionCallStandard.xml | 24 + .../JumbledIncrementerStandard.xml | 25 + .../UnconditionalIfStatementStandard.xml | 39 + .../UnnecessaryFinalModifierStandard.xml | 29 + .../UnusedFunctionParameterStandard.xml | 25 + .../UselessOverridingMethodStandard.xml | 32 + .../Generic/Docs/Commenting/FixmeStandard.xml | 25 + .../Generic/Docs/Commenting/TodoStandard.xml | 25 + .../DisallowYodaConditionsStandard.xml | 23 + .../InlineControlStructureStandard.xml | 22 + .../Generic/Docs/Debug/CSSLintStandard.xml | 19 + .../Docs/Debug/ClosureLinterStandard.xml | 19 + .../Generic/Docs/Debug/JSHintStandard.xml | 19 + .../Docs/Files/ByteOrderMarkStandard.xml | 7 + .../Docs/Files/EndFileNewlineStandard.xml | 7 + .../Docs/Files/EndFileNoNewlineStandard.xml | 7 + .../Docs/Files/ExecutableFileStandard.xml | 7 + .../Generic/Docs/Files/InlineHTMLStandard.xml | 24 + .../Docs/Files/LineEndingsStandard.xml | 7 + .../Generic/Docs/Files/LineLengthStandard.xml | 7 + .../Docs/Files/LowercasedFilenameStandard.xml | 7 + .../Docs/Files/OneClassPerFileStandard.xml | 29 + .../Files/OneInterfacePerFileStandard.xml | 29 + .../OneObjectStructurePerFileStandard.xml | 29 + .../Docs/Files/OneTraitPerFileStandard.xml | 29 + .../DisallowMultipleStatementsStandard.xml | 20 + .../MultipleStatementAlignmentStandard.xml | 56 + .../Formatting/NoSpaceAfterCastStandard.xml | 19 + .../Formatting/SpaceAfterCastStandard.xml | 19 + .../Docs/Formatting/SpaceAfterNotStandard.xml | 25 + .../CallTimePassByReferenceStandard.xml | 31 + .../FunctionCallArgumentSpacingStandard.xml | 39 + .../OpeningFunctionBraceBsdAllmanStandard.xml | 24 + ...gFunctionBraceKernighanRitchieStandard.xml | 24 + .../Metrics/CyclomaticComplexityStandard.xml | 7 + .../Docs/Metrics/NestingLevelStandard.xml | 7 + .../AbstractClassNamePrefixStandard.xml | 23 + .../CamelCapsFunctionNameStandard.xml | 23 + .../ConstructorNameStandard.xml | 29 + .../InterfaceNameSuffixStandard.xml | 23 + .../TraitNameSuffixStandard.xml | 23 + .../UpperCaseConstantNameStandard.xml | 29 + .../Docs/PHP/BacktickOperatorStandard.xml | 7 + .../CharacterBeforePHPOpeningTagStandard.xml | 22 + .../Docs/PHP/ClosingPHPTagStandard.xml | 22 + .../Docs/PHP/DeprecatedFunctionsStandard.xml | 19 + .../DisallowAlternativePHPTagsStandard.xml | 7 + .../DisallowRequestSuperglobalStandard.xml | 7 + .../Docs/PHP/DisallowShortOpenTagStandard.xml | 7 + .../Docs/PHP/DiscourageGotoStandard.xml | 7 + .../Docs/PHP/ForbiddenFunctionsStandard.xml | 19 + .../Docs/PHP/LowerCaseConstantStandard.xml | 23 + .../Docs/PHP/LowerCaseKeywordStandard.xml | 19 + .../Docs/PHP/LowerCaseTypeStandard.xml | 38 + .../Docs/PHP/NoSilencedErrorsStandard.xml | 23 + .../Generic/Docs/PHP/SAPIUsageStandard.xml | 23 + .../Docs/PHP/UpperCaseConstantStandard.xml | 23 + .../UnnecessaryStringConcatStandard.xml | 19 + .../SubversionPropertiesStandard.xml | 7 + .../ArbitraryParenthesesSpacingStandard.xml | 26 + .../DisallowSpaceIndentStandard.xml | 7 + .../WhiteSpace/DisallowTabIndentStandard.xml | 7 + .../Docs/WhiteSpace/ScopeIndentStandard.xml | 23 + .../SpreadOperatorSpacingAfterStandard.xml | 34 + .../Sniffs/Arrays/ArrayIndentSniff.php | 177 + .../Arrays/DisallowLongArraySyntaxSniff.php | 78 + .../Arrays/DisallowShortArraySyntaxSniff.php | 61 + .../Classes/DuplicateClassNameSniff.php | 118 + .../Classes/OpeningBraceSameLineSniff.php | 124 + .../AssignmentInConditionSniff.php | 171 + .../CodeAnalysis/EmptyPHPStatementSniff.php | 162 + .../CodeAnalysis/EmptyStatementSniff.php | 97 + .../ForLoopShouldBeWhileLoopSniff.php | 91 + .../ForLoopWithTestFunctionCallSniff.php | 101 + .../CodeAnalysis/JumbledIncrementerSniff.php | 134 + .../UnconditionalIfStatementSniff.php | 93 + .../UnnecessaryFinalModifierSniff.php | 85 + .../UnusedFunctionParameterSniff.php | 265 ++ .../UselessOverridingMethodSniff.php | 161 + .../Sniffs/Commenting/DocCommentSniff.php | 353 ++ .../Generic/Sniffs/Commenting/FixmeSniff.php | 78 + .../Generic/Sniffs/Commenting/TodoSniff.php | 77 + .../DisallowYodaConditionsSniff.php | 188 + .../InlineControlStructureSniff.php | 381 ++ .../Generic/Sniffs/Debug/CSSLintSniff.php | 96 + .../Sniffs/Debug/ClosureLinterSniff.php | 117 + .../Generic/Sniffs/Debug/ESLintSniff.php | 113 + .../Generic/Sniffs/Debug/JSHintSniff.php | 95 + .../Sniffs/Files/ByteOrderMarkSniff.php | 80 + .../Sniffs/Files/EndFileNewlineSniff.php | 84 + .../Sniffs/Files/EndFileNoNewlineSniff.php | 91 + .../Sniffs/Files/ExecutableFileSniff.php | 62 + .../Generic/Sniffs/Files/InlineHTMLSniff.php | 79 + .../Generic/Sniffs/Files/LineEndingsSniff.php | 148 + .../Generic/Sniffs/Files/LineLengthSniff.php | 201 + .../Sniffs/Files/LowercasedFilenameSniff.php | 70 + .../Sniffs/Files/OneClassPerFileSniff.php | 57 + .../Sniffs/Files/OneInterfacePerFileSniff.php | 57 + .../Files/OneObjectStructurePerFileSniff.php | 62 + .../Sniffs/Files/OneTraitPerFileSniff.php | 57 + .../DisallowMultipleStatementsSniff.php | 105 + .../MultipleStatementAlignmentSniff.php | 426 ++ .../Formatting/NoSpaceAfterCastSniff.php | 61 + .../Sniffs/Formatting/SpaceAfterCastSniff.php | 153 + .../Sniffs/Formatting/SpaceAfterNotSniff.php | 135 + .../Formatting/SpaceBeforeCastSniff.php | 73 + .../CallTimePassByReferenceSniff.php | 141 + .../FunctionCallArgumentSpacingSniff.php | 185 + .../OpeningFunctionBraceBsdAllmanSniff.php | 227 + ...ningFunctionBraceKernighanRitchieSniff.php | 184 + .../Metrics/CyclomaticComplexitySniff.php | 117 + .../Sniffs/Metrics/NestingLevelSniff.php | 100 + .../AbstractClassNamePrefixSniff.php | 60 + .../CamelCapsFunctionNameSniff.php | 223 + .../ConstructorNameSniff.php | 163 + .../InterfaceNameSuffixSniff.php | 54 + .../TraitNameSuffixSniff.php | 54 + .../UpperCaseConstantNameSniff.php | 141 + .../Sniffs/PHP/BacktickOperatorSniff.php | 48 + .../PHP/CharacterBeforePHPOpeningTagSniff.php | 86 + .../Generic/Sniffs/PHP/ClosingPHPTagSniff.php | 54 + .../Sniffs/PHP/DeprecatedFunctionsSniff.php | 73 + .../PHP/DisallowAlternativePHPTagsSniff.php | 253 ++ .../PHP/DisallowRequestSuperglobalSniff.php | 54 + .../Sniffs/PHP/DisallowShortOpenTagSniff.php | 168 + .../Sniffs/PHP/DiscourageGotoSniff.php | 50 + .../Sniffs/PHP/ForbiddenFunctionsSniff.php | 240 ++ .../Sniffs/PHP/LowerCaseConstantSniff.php | 177 + .../Sniffs/PHP/LowerCaseKeywordSniff.php | 85 + .../Generic/Sniffs/PHP/LowerCaseTypeSniff.php | 275 ++ .../Sniffs/PHP/NoSilencedErrorsSniff.php | 77 + .../Sniffs/PHP/RequireStrictTypesSniff.php | 69 + .../Generic/Sniffs/PHP/SAPIUsageSniff.php | 67 + .../Generic/Sniffs/PHP/SyntaxSniff.php | 75 + .../Sniffs/PHP/UpperCaseConstantSniff.php | 59 + .../Strings/UnnecessaryStringConcatSniff.php | 125 + .../VersionControl/GitMergeConflictSniff.php | 228 + .../SubversionPropertiesSniff.php | 186 + .../ArbitraryParenthesesSpacingSniff.php | 238 ++ .../WhiteSpace/DisallowSpaceIndentSniff.php | 220 + .../WhiteSpace/DisallowTabIndentSniff.php | 190 + .../IncrementDecrementSpacingSniff.php | 170 + .../LanguageConstructSpacingSniff.php | 146 + .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 1578 +++++++ .../SpreadOperatorSpacingAfterSniff.php | 146 + .../Tests/Arrays/ArrayIndentUnitTest.inc | 100 + .../Arrays/ArrayIndentUnitTest.inc.fixed | 101 + .../Tests/Arrays/ArrayIndentUnitTest.php | 67 + .../DisallowLongArraySyntaxUnitTest.1.inc | 28 + ...isallowLongArraySyntaxUnitTest.1.inc.fixed | 28 + .../DisallowLongArraySyntaxUnitTest.2.inc | 17 + ...isallowLongArraySyntaxUnitTest.2.inc.fixed | 17 + .../DisallowLongArraySyntaxUnitTest.php | 66 + .../DisallowShortArraySyntaxUnitTest.inc | 12 + ...DisallowShortArraySyntaxUnitTest.inc.fixed | 12 + .../DisallowShortArraySyntaxUnitTest.php | 53 + .../Classes/DuplicateClassNameUnitTest.1.inc | 14 + .../Classes/DuplicateClassNameUnitTest.2.inc | 6 + .../Classes/DuplicateClassNameUnitTest.3.inc | 10 + .../Classes/DuplicateClassNameUnitTest.4.inc | 5 + .../Classes/DuplicateClassNameUnitTest.5.inc | 8 + .../Classes/DuplicateClassNameUnitTest.6.inc | 12 + .../Classes/DuplicateClassNameUnitTest.php | 79 + .../Classes/OpeningBraceSameLineUnitTest.inc | 95 + .../OpeningBraceSameLineUnitTest.inc.fixed | 95 + .../Classes/OpeningBraceSameLineUnitTest.php | 62 + .../AssignmentInConditionUnitTest.inc | 95 + .../AssignmentInConditionUnitTest.php | 83 + .../EmptyPHPStatementUnitTest.inc | 86 + .../EmptyPHPStatementUnitTest.inc.fixed | 80 + .../EmptyPHPStatementUnitTest.php | 68 + .../CodeAnalysis/EmptyStatementUnitTest.inc | 74 + .../CodeAnalysis/EmptyStatementUnitTest.php | 63 + .../ForLoopShouldBeWhileLoopUnitTest.inc | 13 + .../ForLoopShouldBeWhileLoopUnitTest.php | 51 + .../ForLoopWithTestFunctionCallUnitTest.inc | 15 + .../ForLoopWithTestFunctionCallUnitTest.php | 51 + .../JumbledIncrementerUnitTest.inc | 25 + .../JumbledIncrementerUnitTest.php | 52 + .../UnconditionalIfStatementUnitTest.inc | 13 + .../UnconditionalIfStatementUnitTest.php | 52 + .../UnnecessaryFinalModifierUnitTest.inc | 29 + .../UnnecessaryFinalModifierUnitTest.php | 53 + .../UnusedFunctionParameterUnitTest.inc | 154 + .../UnusedFunctionParameterUnitTest.php | 58 + .../UselessOverridingMethodUnitTest.inc | 25 + .../UselessOverridingMethodUnitTest.php | 51 + .../Tests/Commenting/DocCommentUnitTest.inc | 252 ++ .../Commenting/DocCommentUnitTest.inc.fixed | 257 ++ .../Tests/Commenting/DocCommentUnitTest.js | 250 ++ .../Commenting/DocCommentUnitTest.js.fixed | 255 ++ .../Tests/Commenting/DocCommentUnitTest.php | 111 + .../Tests/Commenting/FixmeUnitTest.inc | 23 + .../Generic/Tests/Commenting/FixmeUnitTest.js | 23 + .../Tests/Commenting/FixmeUnitTest.php | 62 + .../Generic/Tests/Commenting/TodoUnitTest.inc | 23 + .../Generic/Tests/Commenting/TodoUnitTest.js | 23 + .../Generic/Tests/Commenting/TodoUnitTest.php | 61 + .../DisallowYodaConditionsUnitTest.inc | 175 + .../DisallowYodaConditionsUnitTest.php | 85 + .../InlineControlStructureUnitTest.1.inc | 274 ++ ...InlineControlStructureUnitTest.1.inc.fixed | 309 ++ .../InlineControlStructureUnitTest.2.inc | 8 + .../InlineControlStructureUnitTest.3.inc | 4 + .../InlineControlStructureUnitTest.4.inc | 5 + .../InlineControlStructureUnitTest.5.inc | 4 + .../InlineControlStructureUnitTest.6.inc | 6 + .../InlineControlStructureUnitTest.7.inc | 16 + .../InlineControlStructureUnitTest.js | 31 + .../InlineControlStructureUnitTest.js.fixed | 39 + .../InlineControlStructureUnitTest.php | 112 + .../Generic/Tests/Debug/CSSLintUnitTest.css | 6 + .../Generic/Tests/Debug/CSSLintUnitTest.php | 70 + .../Tests/Debug/ClosureLinterUnitTest.js | 6 + .../Tests/Debug/ClosureLinterUnitTest.php | 69 + .../Generic/Tests/Debug/ESLintUnitTest.js | 1 + .../Generic/Tests/Debug/ESLintUnitTest.php | 113 + .../Generic/Tests/Debug/JSHintUnitTest.js | 3 + .../Generic/Tests/Debug/JSHintUnitTest.php | 67 + .../Tests/Files/ByteOrderMarkUnitTest.inc | 3 + .../Tests/Files/ByteOrderMarkUnitTest.php | 48 + .../Tests/Files/EndFileNewlineUnitTest.1.css | 3 + .../Tests/Files/EndFileNewlineUnitTest.1.inc | 3 + .../Tests/Files/EndFileNewlineUnitTest.1.js | 3 + .../Tests/Files/EndFileNewlineUnitTest.2.css | 2 + .../Tests/Files/EndFileNewlineUnitTest.2.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.2.js | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.css | 2 + .../Files/EndFileNewlineUnitTest.3.css.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.inc | 2 + .../Files/EndFileNewlineUnitTest.3.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.js | 2 + .../Files/EndFileNewlineUnitTest.3.js.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.4.inc | 2 + .../Files/EndFileNewlineUnitTest.4.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.5.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.6.inc | 1 + .../Files/EndFileNewlineUnitTest.6.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.7.inc | 1 + .../Files/EndFileNewlineUnitTest.7.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.8.inc | 1 + .../Tests/Files/EndFileNewlineUnitTest.php | 63 + .../Files/EndFileNoNewlineUnitTest.1.css | 3 + .../EndFileNoNewlineUnitTest.1.css.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.1.inc | 3 + .../EndFileNoNewlineUnitTest.1.inc.fixed | 2 + .../Tests/Files/EndFileNoNewlineUnitTest.1.js | 3 + .../Files/EndFileNoNewlineUnitTest.1.js.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.10.inc | 1 + .../Files/EndFileNoNewlineUnitTest.2.css | 2 + .../EndFileNoNewlineUnitTest.2.css.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.2.inc | 3 + .../EndFileNoNewlineUnitTest.2.inc.fixed | 3 + .../Tests/Files/EndFileNoNewlineUnitTest.2.js | 2 + .../Files/EndFileNoNewlineUnitTest.2.js.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.3.css | 2 + .../Files/EndFileNoNewlineUnitTest.3.inc | 2 + .../Tests/Files/EndFileNoNewlineUnitTest.3.js | 2 + .../Files/EndFileNoNewlineUnitTest.4.inc | 3 + .../Files/EndFileNoNewlineUnitTest.5.inc | 2 + .../Files/EndFileNoNewlineUnitTest.6.inc | 2 + .../EndFileNoNewlineUnitTest.6.inc.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.7.inc | 6 + .../Files/EndFileNoNewlineUnitTest.8.inc | 1 + .../EndFileNoNewlineUnitTest.8.inc.fixed | 1 + .../Files/EndFileNoNewlineUnitTest.9.inc | 1 + .../EndFileNoNewlineUnitTest.9.inc.fixed | 1 + .../Tests/Files/EndFileNoNewlineUnitTest.php | 67 + .../Tests/Files/ExecutableFileUnitTest.1.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.2.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.3.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.4.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.php | 73 + .../Tests/Files/InlineHTMLUnitTest.1.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.2.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.3.inc | 6 + .../Tests/Files/InlineHTMLUnitTest.4.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.5.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.6.inc | 2 + .../Tests/Files/InlineHTMLUnitTest.7.inc | 2 + .../Tests/Files/InlineHTMLUnitTest.php | 65 + .../Tests/Files/LineEndingsUnitTest.1.inc | 18 + .../Files/LineEndingsUnitTest.1.inc.fixed | 18 + .../Tests/Files/LineEndingsUnitTest.2.inc | 5 + .../Files/LineEndingsUnitTest.2.inc.fixed | 5 + .../Tests/Files/LineEndingsUnitTest.css | 3 + .../Tests/Files/LineEndingsUnitTest.css.fixed | 3 + .../Tests/Files/LineEndingsUnitTest.js | 2 + .../Tests/Files/LineEndingsUnitTest.js.fixed | 2 + .../Tests/Files/LineEndingsUnitTest.php | 63 + .../Tests/Files/LineLengthUnitTest.1.inc | 84 + .../Tests/Files/LineLengthUnitTest.2.inc | 7 + .../Tests/Files/LineLengthUnitTest.3.inc | 16 + .../Tests/Files/LineLengthUnitTest.4.inc | 16 + .../Tests/Files/LineLengthUnitTest.php | 111 + .../Files/LowercasedFilenameUnitTest.1.inc | 7 + .../Files/LowercasedFilenameUnitTest.2.inc | 7 + .../Files/LowercasedFilenameUnitTest.php | 56 + .../Tests/Files/OneClassPerFileUnitTest.inc | 13 + .../Tests/Files/OneClassPerFileUnitTest.php | 51 + .../Files/OneInterfacePerFileUnitTest.inc | 13 + .../Files/OneInterfacePerFileUnitTest.php | 51 + .../OneObjectStructurePerFileUnitTest.inc | 26 + .../OneObjectStructurePerFileUnitTest.php | 54 + .../Tests/Files/OneTraitPerFileUnitTest.inc | 17 + .../Tests/Files/OneTraitPerFileUnitTest.php | 51 + .../DisallowMultipleStatementsUnitTest.inc | 20 + ...sallowMultipleStatementsUnitTest.inc.fixed | 25 + .../DisallowMultipleStatementsUnitTest.php | 54 + .../MultipleStatementAlignmentUnitTest.inc | 504 +++ ...ltipleStatementAlignmentUnitTest.inc.fixed | 504 +++ .../MultipleStatementAlignmentUnitTest.js | 118 + ...ultipleStatementAlignmentUnitTest.js.fixed | 118 + .../MultipleStatementAlignmentUnitTest.php | 166 + .../Formatting/NoSpaceAfterCastUnitTest.inc | 51 + .../NoSpaceAfterCastUnitTest.inc.fixed | 51 + .../Formatting/NoSpaceAfterCastUnitTest.php | 72 + .../Formatting/SpaceAfterCastUnitTest.inc | 95 + .../SpaceAfterCastUnitTest.inc.fixed | 92 + .../Formatting/SpaceAfterCastUnitTest.php | 87 + .../Formatting/SpaceAfterNotUnitTest.inc | 86 + .../SpaceAfterNotUnitTest.inc.fixed | 83 + .../Tests/Formatting/SpaceAfterNotUnitTest.js | 5 + .../Formatting/SpaceAfterNotUnitTest.js.fixed | 5 + .../Formatting/SpaceAfterNotUnitTest.php | 91 + .../Formatting/SpaceBeforeCastUnitTest.inc | 65 + .../SpaceBeforeCastUnitTest.inc.fixed | 65 + .../Formatting/SpaceBeforeCastUnitTest.php | 78 + .../CallTimePassByReferenceUnitTest.inc | 39 + .../CallTimePassByReferenceUnitTest.php | 55 + .../FunctionCallArgumentSpacingUnitTest.inc | 155 + ...ctionCallArgumentSpacingUnitTest.inc.fixed | 155 + .../FunctionCallArgumentSpacingUnitTest.php | 77 + .../OpeningFunctionBraceBsdAllmanUnitTest.inc | 263 ++ ...ngFunctionBraceBsdAllmanUnitTest.inc.fixed | 280 ++ .../OpeningFunctionBraceBsdAllmanUnitTest.php | 84 + ...gFunctionBraceKernighanRitchieUnitTest.inc | 210 + ...ionBraceKernighanRitchieUnitTest.inc.fixed | 198 + ...gFunctionBraceKernighanRitchieUnitTest.php | 75 + .../Metrics/CyclomaticComplexityUnitTest.inc | 454 ++ .../Metrics/CyclomaticComplexityUnitTest.php | 58 + .../Tests/Metrics/NestingLevelUnitTest.inc | 102 + .../Tests/Metrics/NestingLevelUnitTest.php | 51 + .../AbstractClassNamePrefixUnitTest.inc | 59 + .../AbstractClassNamePrefixUnitTest.php | 53 + .../CamelCapsFunctionNameUnitTest.inc | 185 + .../CamelCapsFunctionNameUnitTest.php | 92 + .../ConstructorNameUnitTest.inc | 97 + .../ConstructorNameUnitTest.php | 54 + .../InterfaceNameSuffixUnitTest.inc | 27 + .../InterfaceNameSuffixUnitTest.php | 47 + .../TraitNameSuffixUnitTest.inc | 13 + .../TraitNameSuffixUnitTest.php | 50 + .../UpperCaseConstantNameUnitTest.inc | 33 + .../UpperCaseConstantNameUnitTest.php | 56 + .../Tests/PHP/BacktickOperatorUnitTest.inc | 2 + .../Tests/PHP/BacktickOperatorUnitTest.php | 48 + ...CharacterBeforePHPOpeningTagUnitTest.1.inc | 9 + ...CharacterBeforePHPOpeningTagUnitTest.2.inc | 4 + ...CharacterBeforePHPOpeningTagUnitTest.3.inc | 3 + .../CharacterBeforePHPOpeningTagUnitTest.php | 57 + .../Tests/PHP/ClosingPHPTagUnitTest.1.inc | 10 + .../Tests/PHP/ClosingPHPTagUnitTest.2.inc | 5 + .../Tests/PHP/ClosingPHPTagUnitTest.php | 59 + .../Tests/PHP/DeprecatedFunctionsUnitTest.inc | 4 + .../Tests/PHP/DeprecatedFunctionsUnitTest.php | 58 + .../DisallowAlternativePHPTagsUnitTest.1.inc | 14 + ...llowAlternativePHPTagsUnitTest.1.inc.fixed | 14 + .../DisallowAlternativePHPTagsUnitTest.2.inc | 6 + ...llowAlternativePHPTagsUnitTest.2.inc.fixed | 6 + .../DisallowAlternativePHPTagsUnitTest.3.inc | 7 + .../DisallowAlternativePHPTagsUnitTest.php | 105 + .../DisallowRequestSuperglobalUnitTest.inc | 16 + .../DisallowRequestSuperglobalUnitTest.php | 51 + .../PHP/DisallowShortOpenTagUnitTest.1.inc | 11 + .../DisallowShortOpenTagUnitTest.1.inc.fixed | 11 + .../PHP/DisallowShortOpenTagUnitTest.2.inc | 8 + .../DisallowShortOpenTagUnitTest.2.inc.fixed | 8 + .../PHP/DisallowShortOpenTagUnitTest.3.inc | 16 + .../PHP/DisallowShortOpenTagUnitTest.php | 103 + .../Tests/PHP/DiscourageGotoUnitTest.inc | 18 + .../Tests/PHP/DiscourageGotoUnitTest.php | 53 + .../Tests/PHP/ForbiddenFunctionsUnitTest.inc | 57 + .../Tests/PHP/ForbiddenFunctionsUnitTest.php | 54 + .../Tests/PHP/LowerCaseConstantUnitTest.inc | 100 + .../PHP/LowerCaseConstantUnitTest.inc.fixed | 100 + .../Tests/PHP/LowerCaseConstantUnitTest.js | 14 + .../PHP/LowerCaseConstantUnitTest.js.fixed | 14 + .../Tests/PHP/LowerCaseConstantUnitTest.php | 91 + .../Tests/PHP/LowerCaseKeywordUnitTest.inc | 48 + .../PHP/LowerCaseKeywordUnitTest.inc.fixed | 48 + .../Tests/PHP/LowerCaseKeywordUnitTest.php | 66 + .../Tests/PHP/LowerCaseTypeUnitTest.inc | 91 + .../Tests/PHP/LowerCaseTypeUnitTest.inc.fixed | 91 + .../Tests/PHP/LowerCaseTypeUnitTest.php | 89 + .../Tests/PHP/NoSilencedErrorsUnitTest.inc | 10 + .../Tests/PHP/NoSilencedErrorsUnitTest.php | 51 + .../PHP/RequireStrictTypesUnitTest.1.inc | 8 + .../PHP/RequireStrictTypesUnitTest.2.inc | 2 + .../Tests/PHP/RequireStrictTypesUnitTest.php | 56 + .../Generic/Tests/PHP/SAPIUsageUnitTest.inc | 5 + .../Generic/Tests/PHP/SAPIUsageUnitTest.php | 48 + .../Generic/Tests/PHP/SyntaxUnitTest.1.inc | 4 + .../Generic/Tests/PHP/SyntaxUnitTest.2.inc | 3 + .../Generic/Tests/PHP/SyntaxUnitTest.php | 59 + .../Tests/PHP/UpperCaseConstantUnitTest.inc | 98 + .../PHP/UpperCaseConstantUnitTest.inc.fixed | 98 + .../Tests/PHP/UpperCaseConstantUnitTest.php | 70 + .../UnnecessaryStringConcatUnitTest.inc | 21 + .../UnnecessaryStringConcatUnitTest.js | 15 + .../UnnecessaryStringConcatUnitTest.php | 73 + .../GitMergeConflictUnitTest.1.css | 35 + .../GitMergeConflictUnitTest.1.inc | 61 + .../GitMergeConflictUnitTest.2.css | 32 + .../GitMergeConflictUnitTest.2.inc | 31 + .../GitMergeConflictUnitTest.3.inc | 43 + .../GitMergeConflictUnitTest.4.inc | 71 + .../GitMergeConflictUnitTest.5.inc | 34 + .../GitMergeConflictUnitTest.6.inc | 34 + .../GitMergeConflictUnitTest.7.inc | 19 + .../GitMergeConflictUnitTest.js | 33 + .../GitMergeConflictUnitTest.php | 170 + .../SubversionPropertiesUnitTest.inc | 3 + .../SubversionPropertiesUnitTest.php | 61 + .../ArbitraryParenthesesSpacingUnitTest.inc | 165 + ...itraryParenthesesSpacingUnitTest.inc.fixed | 153 + .../ArbitraryParenthesesSpacingUnitTest.php | 85 + .../DisallowSpaceIndentUnitTest.1.inc | 118 + .../DisallowSpaceIndentUnitTest.1.inc.fixed | 118 + .../DisallowSpaceIndentUnitTest.2.inc | 118 + .../DisallowSpaceIndentUnitTest.2.inc.fixed | 118 + .../DisallowSpaceIndentUnitTest.3.inc | 19 + .../DisallowSpaceIndentUnitTest.3.inc.fixed | 19 + .../DisallowSpaceIndentUnitTest.css | 4 + .../DisallowSpaceIndentUnitTest.css.fixed | 4 + .../WhiteSpace/DisallowSpaceIndentUnitTest.js | 9 + .../DisallowSpaceIndentUnitTest.js.fixed | 9 + .../DisallowSpaceIndentUnitTest.php | 129 + .../DisallowTabIndentUnitTest.1.inc | 93 + .../DisallowTabIndentUnitTest.1.inc.fixed | 93 + .../DisallowTabIndentUnitTest.2.inc | 19 + .../DisallowTabIndentUnitTest.2.inc.fixed | 19 + .../WhiteSpace/DisallowTabIndentUnitTest.css | 5 + .../DisallowTabIndentUnitTest.css.fixed | 5 + .../WhiteSpace/DisallowTabIndentUnitTest.js | 9 + .../DisallowTabIndentUnitTest.js.fixed | 9 + .../WhiteSpace/DisallowTabIndentUnitTest.php | 136 + .../IncrementDecrementSpacingUnitTest.inc | 17 + ...ncrementDecrementSpacingUnitTest.inc.fixed | 16 + .../IncrementDecrementSpacingUnitTest.js | 17 + ...IncrementDecrementSpacingUnitTest.js.fixed | 16 + .../IncrementDecrementSpacingUnitTest.php | 66 + .../LanguageConstructSpacingUnitTest.inc | 79 + ...LanguageConstructSpacingUnitTest.inc.fixed | 73 + .../LanguageConstructSpacingUnitTest.php | 74 + .../WhiteSpace/ScopeIndentUnitTest.1.inc | 1611 +++++++ .../ScopeIndentUnitTest.1.inc.fixed | 1611 +++++++ .../Tests/WhiteSpace/ScopeIndentUnitTest.1.js | 239 ++ .../WhiteSpace/ScopeIndentUnitTest.1.js.fixed | 239 ++ .../WhiteSpace/ScopeIndentUnitTest.2.inc | 1611 +++++++ .../ScopeIndentUnitTest.2.inc.fixed | 1611 +++++++ .../WhiteSpace/ScopeIndentUnitTest.3.inc | 28 + .../ScopeIndentUnitTest.3.inc.fixed | 28 + .../WhiteSpace/ScopeIndentUnitTest.4.inc | 6 + .../Tests/WhiteSpace/ScopeIndentUnitTest.php | 214 + .../SpreadOperatorSpacingAfterUnitTest.inc | 73 + ...readOperatorSpacingAfterUnitTest.inc.fixed | 68 + .../SpreadOperatorSpacingAfterUnitTest.php | 58 + .../src/Standards/Generic/ruleset.xml | 4 + .../Sniffs/CSS/BrowserSpecificStylesSniff.php | 87 + .../Channels/DisallowSelfActionsSniff.php | 125 + .../Sniffs/Channels/IncludeOwnSystemSniff.php | 98 + .../Sniffs/Channels/IncludeSystemSniff.php | 314 ++ .../Sniffs/Channels/UnusedSystemSniff.php | 141 + .../Commenting/FunctionCommentSniff.php | 84 + .../MySource/Sniffs/Debug/DebugCodeSniff.php | 55 + .../Sniffs/Debug/FirebugConsoleSniff.php | 64 + .../Sniffs/Objects/AssignThisSniff.php | 81 + .../Objects/CreateWidgetTypeCallbackSniff.php | 218 + .../Sniffs/Objects/DisallowNewWidgetSniff.php | 59 + .../Sniffs/PHP/AjaxNullComparisonSniff.php | 103 + .../Sniffs/PHP/EvalObjectFactorySniff.php | 114 + .../Sniffs/PHP/GetRequestDataSniff.php | 106 + .../Sniffs/PHP/ReturnFunctionValueSniff.php | 63 + .../Sniffs/Strings/JoinStringsSniff.php | 76 + .../CSS/BrowserSpecificStylesUnitTest.css | 13 + .../CSS/BrowserSpecificStylesUnitTest.php | 48 + .../Channels/DisallowSelfActionsUnitTest.inc | 51 + .../Channels/DisallowSelfActionsUnitTest.php | 53 + .../Tests/Channels/IncludeSystemUnitTest.inc | 112 + .../Tests/Channels/IncludeSystemUnitTest.php | 60 + .../Tests/Channels/UnusedSystemUnitTest.inc | 67 + .../Tests/Channels/UnusedSystemUnitTest.php | 55 + .../Commenting/FunctionCommentUnitTest.inc | 101 + .../Commenting/FunctionCommentUnitTest.php | 54 + .../Tests/Debug/DebugCodeUnitTest.inc | 4 + .../Tests/Debug/DebugCodeUnitTest.php | 51 + .../Tests/Debug/FirebugConsoleUnitTest.js | 8 + .../Tests/Debug/FirebugConsoleUnitTest.php | 61 + .../Tests/Objects/AssignThisUnitTest.js | 20 + .../Tests/Objects/AssignThisUnitTest.php | 58 + .../CreateWidgetTypeCallbackUnitTest.js | 186 + .../CreateWidgetTypeCallbackUnitTest.php | 59 + .../Objects/DisallowNewWidgetUnitTest.inc | 6 + .../Objects/DisallowNewWidgetUnitTest.php | 48 + .../Tests/PHP/AjaxNullComparisonUnitTest.inc | 182 + .../Tests/PHP/AjaxNullComparisonUnitTest.php | 55 + .../Tests/PHP/EvalObjectFactoryUnitTest.inc | 26 + .../Tests/PHP/EvalObjectFactoryUnitTest.php | 52 + .../Tests/PHP/GetRequestDataUnitTest.inc | 30 + .../Tests/PHP/GetRequestDataUnitTest.php | 56 + .../Tests/PHP/ReturnFunctionValueUnitTest.inc | 9 + .../Tests/PHP/ReturnFunctionValueUnitTest.php | 52 + .../Tests/Strings/JoinStringsUnitTest.js | 18 + .../Tests/Strings/JoinStringsUnitTest.php | 62 + .../src/Standards/MySource/ruleset.xml | 18 + .../Docs/Classes/ClassDeclarationStandard.xml | 22 + .../Docs/Commenting/ClassCommentStandard.xml | 177 + .../Docs/Commenting/FileCommentStandard.xml | 286 ++ .../Commenting/FunctionCommentStandard.xml | 230 + .../Docs/Commenting/InlineCommentStandard.xml | 19 + .../ControlSignatureStandard.xml | 36 + .../MultiLineConditionStandard.xml | 60 + .../PEAR/Docs/Files/IncludingFileStandard.xml | 24 + .../PEAR/Docs/Files/LineLengthStandard.xml | 7 + .../MultiLineAssignmentStandard.xml | 35 + .../FunctionCallSignatureStandard.xml | 19 + .../Functions/FunctionDeclarationStandard.xml | 41 + .../Functions/ValidDefaultValueStandard.xml | 25 + .../ValidClassNameStandard.xml | 23 + .../ValidFunctionNameStandard.xml | 23 + .../ValidVariableNameStandard.xml | 29 + .../ObjectOperatorIndentStandard.xml | 39 + .../WhiteSpace/ScopeClosingBraceStandard.xml | 23 + .../Docs/WhiteSpace/ScopeIndentStandard.xml | 29 + .../Sniffs/Classes/ClassDeclarationSniff.php | 150 + .../Sniffs/Commenting/ClassCommentSniff.php | 119 + .../Sniffs/Commenting/FileCommentSniff.php | 582 +++ .../Commenting/FunctionCommentSniff.php | 525 +++ .../Sniffs/Commenting/InlineCommentSniff.php | 68 + .../ControlSignatureSniff.php | 48 + .../MultiLineConditionSniff.php | 283 ++ .../PEAR/Sniffs/Files/IncludingFileSniff.php | 136 + .../Formatting/MultiLineAssignmentSniff.php | 106 + .../Functions/FunctionCallSignatureSniff.php | 628 +++ .../Functions/FunctionDeclarationSniff.php | 522 +++ .../Functions/ValidDefaultValueSniff.php | 78 + .../NamingConventions/ValidClassNameSniff.php | 98 + .../ValidFunctionNameSniff.php | 284 ++ .../ValidVariableNameSniff.php | 103 + .../WhiteSpace/ObjectOperatorIndentSniff.php | 204 + .../WhiteSpace/ScopeClosingBraceSniff.php | 179 + .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 24 + .../Classes/ClassDeclarationUnitTest.1.inc | 114 + .../ClassDeclarationUnitTest.1.inc.fixed | 125 + .../Classes/ClassDeclarationUnitTest.2.inc | 11 + .../Classes/ClassDeclarationUnitTest.php | 95 + .../Tests/Commenting/ClassCommentUnitTest.inc | 145 + .../Tests/Commenting/ClassCommentUnitTest.php | 71 + .../Commenting/FileCommentUnitTest.1.inc | 53 + .../Commenting/FileCommentUnitTest.2.inc | 9 + .../Commenting/FileCommentUnitTest.3.inc | 8 + .../Tests/Commenting/FileCommentUnitTest.php | 91 + .../Commenting/FunctionCommentUnitTest.inc | 478 +++ .../FunctionCommentUnitTest.inc.fixed | 478 +++ .../Commenting/FunctionCommentUnitTest.php | 96 + .../Commenting/InlineCommentUnitTest.inc | 29 + .../InlineCommentUnitTest.inc.fixed | 29 + .../Commenting/InlineCommentUnitTest.php | 55 + .../ControlSignatureUnitTest.inc | 165 + .../ControlSignatureUnitTest.php | 72 + .../MultiLineConditionUnitTest.inc | 251 ++ .../MultiLineConditionUnitTest.inc.fixed | 247 ++ .../MultiLineConditionUnitTest.js | 251 ++ .../MultiLineConditionUnitTest.js.fixed | 247 ++ .../MultiLineConditionUnitTest.php | 91 + .../Tests/Files/IncludingFileUnitTest.inc | 99 + .../Files/IncludingFileUnitTest.inc.fixed | 99 + .../Tests/Files/IncludingFileUnitTest.php | 67 + .../MultiLineAssignmentUnitTest.inc | 22 + .../MultiLineAssignmentUnitTest.php | 52 + .../FunctionCallSignatureUnitTest.inc | 550 +++ .../FunctionCallSignatureUnitTest.inc.fixed | 565 +++ .../FunctionCallSignatureUnitTest.js | 80 + .../FunctionCallSignatureUnitTest.js.fixed | 84 + .../FunctionCallSignatureUnitTest.php | 154 + .../Functions/FunctionDeclarationUnitTest.inc | 420 ++ .../FunctionDeclarationUnitTest.inc.fixed | 418 ++ .../Functions/FunctionDeclarationUnitTest.js | 59 + .../FunctionDeclarationUnitTest.js.fixed | 60 + .../Functions/FunctionDeclarationUnitTest.php | 138 + .../Functions/ValidDefaultValueUnitTest.inc | 119 + .../Functions/ValidDefaultValueUnitTest.php | 60 + .../ValidClassNameUnitTest.inc | 90 + .../ValidClassNameUnitTest.php | 73 + .../ValidFunctionNameUnitTest.inc | 243 ++ .../ValidFunctionNameUnitTest.php | 149 + .../ValidVariableNameUnitTest.inc | 101 + .../ValidVariableNameUnitTest.php | 56 + .../ObjectOperatorIndentUnitTest.inc | 142 + .../ObjectOperatorIndentUnitTest.inc.fixed | 142 + .../ObjectOperatorIndentUnitTest.php | 74 + .../WhiteSpace/ScopeClosingBraceUnitTest.inc | 164 + .../ScopeClosingBraceUnitTest.inc.fixed | 170 + .../WhiteSpace/ScopeClosingBraceUnitTest.php | 67 + .../Tests/WhiteSpace/ScopeIndentUnitTest.inc | 314 ++ .../Tests/WhiteSpace/ScopeIndentUnitTest.php | 66 + .../src/Standards/PEAR/ruleset.xml | 41 + .../Docs/Classes/ClassDeclarationStandard.xml | 48 + .../PSR1/Docs/Files/SideEffectsStandard.xml | 27 + .../Methods/CamelCapsMethodNameStandard.xml | 29 + .../Sniffs/Classes/ClassDeclarationSniff.php | 75 + .../PSR1/Sniffs/Files/SideEffectsSniff.php | 299 ++ .../Methods/CamelCapsMethodNameSniff.php | 91 + .../Classes/ClassDeclarationUnitTest.1.inc | 3 + .../Classes/ClassDeclarationUnitTest.2.inc | 4 + .../Classes/ClassDeclarationUnitTest.3.inc | 3 + .../Classes/ClassDeclarationUnitTest.php | 57 + .../Tests/Files/SideEffectsUnitTest.1.inc | 79 + .../Tests/Files/SideEffectsUnitTest.10.inc | 8 + .../Tests/Files/SideEffectsUnitTest.11.inc | 11 + .../Tests/Files/SideEffectsUnitTest.12.inc | 8 + .../Tests/Files/SideEffectsUnitTest.13.inc | 2 + .../Tests/Files/SideEffectsUnitTest.14.inc | 2 + .../Tests/Files/SideEffectsUnitTest.15.inc | 2 + .../Tests/Files/SideEffectsUnitTest.16.inc | 2 + .../Tests/Files/SideEffectsUnitTest.2.inc | 24 + .../Tests/Files/SideEffectsUnitTest.3.inc | 6 + .../Tests/Files/SideEffectsUnitTest.4.inc | 10 + .../Tests/Files/SideEffectsUnitTest.5.inc | 2 + .../Tests/Files/SideEffectsUnitTest.6.inc | 9 + .../Tests/Files/SideEffectsUnitTest.7.inc | 8 + .../Tests/Files/SideEffectsUnitTest.8.inc | 8 + .../Tests/Files/SideEffectsUnitTest.9.inc | 8 + .../PSR1/Tests/Files/SideEffectsUnitTest.php | 80 + .../Methods/CamelCapsMethodNameUnitTest.inc | 81 + .../Methods/CamelCapsMethodNameUnitTest.php | 59 + .../src/Standards/PSR1/ruleset.xml | 47 + .../Classes/ClassInstantiationStandard.xml | 19 + .../NullableTypeDeclarationStandard.xml | 45 + .../ShortFormTypeKeywordsStandard.xml | 19 + .../CompoundNamespaceDepthStandard.xml | 28 + .../Operators/OperatorSpacingStandard.xml | 27 + .../Classes/AnonClassDeclarationSniff.php | 242 ++ .../Classes/ClassInstantiationSniff.php | 114 + .../Sniffs/Classes/ClosingBraceSniff.php | 67 + .../Sniffs/Classes/OpeningBraceSpaceSniff.php | 80 + .../BooleanOperatorPlacementSniff.php | 229 + .../ControlStructureSpacingSniff.php | 192 + .../Sniffs/Files/DeclareStatementSniff.php | 256 ++ .../PSR12/Sniffs/Files/FileHeaderSniff.php | 428 ++ .../Sniffs/Files/ImportStatementSniff.php | 77 + .../PSR12/Sniffs/Files/OpenTagSniff.php | 73 + .../NullableTypeDeclarationSniff.php | 91 + .../Functions/ReturnTypeDeclarationSniff.php | 110 + .../Keywords/ShortFormTypeKeywordsSniff.php | 75 + .../CompoundNamespaceDepthSniff.php | 80 + .../Sniffs/Operators/OperatorSpacingSniff.php | 112 + .../Properties/ConstantVisibilitySniff.php | 64 + .../Sniffs/Traits/UseDeclarationSniff.php | 700 +++ .../Classes/AnonClassDeclarationUnitTest.inc | 84 + .../AnonClassDeclarationUnitTest.inc.fixed | 86 + .../Classes/AnonClassDeclarationUnitTest.php | 71 + .../Classes/ClassInstantiationUnitTest.inc | 44 + .../ClassInstantiationUnitTest.inc.fixed | 44 + .../Classes/ClassInstantiationUnitTest.php | 66 + .../Tests/Classes/ClosingBraceUnitTest.inc | 52 + .../Tests/Classes/ClosingBraceUnitTest.php | 55 + .../Classes/OpeningBraceSpaceUnitTest.inc | 57 + .../OpeningBraceSpaceUnitTest.inc.fixed | 48 + .../Classes/OpeningBraceSpaceUnitTest.php | 55 + .../BooleanOperatorPlacementUnitTest.inc | 131 + ...BooleanOperatorPlacementUnitTest.inc.fixed | 141 + .../BooleanOperatorPlacementUnitTest.php | 59 + .../ControlStructureSpacingUnitTest.inc | 100 + .../ControlStructureSpacingUnitTest.inc.fixed | 103 + .../ControlStructureSpacingUnitTest.php | 68 + .../Tests/Files/DeclareStatementUnitTest.inc | 50 + .../Files/DeclareStatementUnitTest.inc.fixed | 54 + .../Tests/Files/DeclareStatementUnitTest.php | 72 + .../Tests/Files/FileHeaderUnitTest.1.inc | 29 + .../Tests/Files/FileHeaderUnitTest.10.inc | 4 + .../Files/FileHeaderUnitTest.10.inc.fixed | 5 + .../Tests/Files/FileHeaderUnitTest.11.inc | 21 + .../Files/FileHeaderUnitTest.11.inc.fixed | 22 + .../Tests/Files/FileHeaderUnitTest.12.inc | 17 + .../Files/FileHeaderUnitTest.12.inc.fixed | 18 + .../Tests/Files/FileHeaderUnitTest.13.inc | 24 + .../Tests/Files/FileHeaderUnitTest.14.inc | 7 + .../Tests/Files/FileHeaderUnitTest.15.inc | 5 + .../Tests/Files/FileHeaderUnitTest.16.inc | 13 + .../Tests/Files/FileHeaderUnitTest.17.inc | 13 + .../Tests/Files/FileHeaderUnitTest.2.inc | 33 + .../Files/FileHeaderUnitTest.2.inc.fixed | 29 + .../Tests/Files/FileHeaderUnitTest.3.inc | 27 + .../Tests/Files/FileHeaderUnitTest.4.inc | 15 + .../Files/FileHeaderUnitTest.4.inc.fixed | 19 + .../Tests/Files/FileHeaderUnitTest.5.inc | 18 + .../Tests/Files/FileHeaderUnitTest.6.inc | 13 + .../Tests/Files/FileHeaderUnitTest.7.inc | 2 + .../Files/FileHeaderUnitTest.7.inc.fixed | 3 + .../Tests/Files/FileHeaderUnitTest.8.inc | 5 + .../Tests/Files/FileHeaderUnitTest.9.inc | 7 + .../PSR12/Tests/Files/FileHeaderUnitTest.php | 82 + .../Tests/Files/ImportStatementUnitTest.inc | 26 + .../Files/ImportStatementUnitTest.inc.fixed | 26 + .../Tests/Files/ImportStatementUnitTest.php | 52 + .../PSR12/Tests/Files/OpenTagUnitTest.1.inc | 3 + .../PSR12/Tests/Files/OpenTagUnitTest.2.inc | 1 + .../Tests/Files/OpenTagUnitTest.2.inc.fixed | 2 + .../PSR12/Tests/Files/OpenTagUnitTest.3.inc | 3 + .../PSR12/Tests/Files/OpenTagUnitTest.4.inc | 2 + .../PSR12/Tests/Files/OpenTagUnitTest.5.inc | 1 + .../PSR12/Tests/Files/OpenTagUnitTest.php | 55 + .../NullableTypeDeclarationUnitTest.inc | 87 + .../NullableTypeDeclarationUnitTest.inc.fixed | 85 + .../NullableTypeDeclarationUnitTest.php | 64 + .../ReturnTypeDeclarationUnitTest.inc | 66 + .../ReturnTypeDeclarationUnitTest.inc.fixed | 62 + .../ReturnTypeDeclarationUnitTest.php | 61 + .../ShortFormTypeKeywordsUnitTest.inc | 14 + .../ShortFormTypeKeywordsUnitTest.inc.fixed | 14 + .../ShortFormTypeKeywordsUnitTest.php | 54 + .../CompoundNamespaceDepthUnitTest.inc | 31 + .../CompoundNamespaceDepthUnitTest.php | 52 + .../Operators/OperatorSpacingUnitTest.inc | 77 + .../OperatorSpacingUnitTest.inc.fixed | 77 + .../Operators/OperatorSpacingUnitTest.php | 69 + .../Properties/ConstantVisibilityUnitTest.inc | 22 + .../Properties/ConstantVisibilityUnitTest.php | 52 + .../Tests/Traits/UseDeclarationUnitTest.inc | 221 + .../Traits/UseDeclarationUnitTest.inc.fixed | 213 + .../Tests/Traits/UseDeclarationUnitTest.php | 71 + .../src/Standards/PSR12/ruleset.xml | 347 ++ .../Docs/Classes/ClassDeclarationStandard.xml | 23 + .../Classes/PropertyDeclarationStandard.xml | 81 + .../ControlStructureSpacingStandard.xml | 23 + .../ElseIfDeclarationStandard.xml | 27 + .../SwitchDeclarationStandard.xml | 104 + .../Docs/Files/EndFileNewlineStandard.xml | 7 + .../Methods/MethodDeclarationStandard.xml | 51 + .../NamespaceDeclarationStandard.xml | 22 + .../Namespaces/UseDeclarationStandard.xml | 57 + .../Sniffs/Classes/ClassDeclarationSniff.php | 528 +++ .../Classes/PropertyDeclarationSniff.php | 185 + .../ControlStructureSpacingSniff.php | 142 + .../ElseIfDeclarationSniff.php | 72 + .../SwitchDeclarationSniff.php | 396 ++ .../PSR2/Sniffs/Files/ClosingTagSniff.php | 89 + .../PSR2/Sniffs/Files/EndFileNewlineSniff.php | 107 + .../Methods/FunctionCallSignatureSniff.php | 79 + .../Methods/FunctionClosingBraceSniff.php | 91 + .../Sniffs/Methods/MethodDeclarationSniff.php | 162 + .../Namespaces/NamespaceDeclarationSniff.php | 100 + .../Sniffs/Namespaces/UseDeclarationSniff.php | 297 ++ .../Classes/ClassDeclarationUnitTest.inc | 241 ++ .../ClassDeclarationUnitTest.inc.fixed | 234 + .../Classes/ClassDeclarationUnitTest.php | 86 + .../Classes/PropertyDeclarationUnitTest.inc | 83 + .../PropertyDeclarationUnitTest.inc.fixed | 80 + .../Classes/PropertyDeclarationUnitTest.php | 77 + .../ControlStructureSpacingUnitTest.inc | 81 + .../ControlStructureSpacingUnitTest.inc.fixed | 80 + .../ControlStructureSpacingUnitTest.php | 62 + .../ElseIfDeclarationUnitTest.inc | 17 + .../ElseIfDeclarationUnitTest.inc.fixed | 17 + .../ElseIfDeclarationUnitTest.php | 51 + .../SwitchDeclarationUnitTest.inc | 598 +++ .../SwitchDeclarationUnitTest.inc.fixed | 593 +++ .../SwitchDeclarationUnitTest.php | 81 + .../PSR2/Tests/Files/ClosingTagUnitTest.1.inc | 12 + .../Files/ClosingTagUnitTest.1.inc.fixed | 12 + .../PSR2/Tests/Files/ClosingTagUnitTest.2.inc | 3 + .../PSR2/Tests/Files/ClosingTagUnitTest.3.inc | 7 + .../PSR2/Tests/Files/ClosingTagUnitTest.4.inc | 1 + .../Files/ClosingTagUnitTest.4.inc.fixed | 1 + .../PSR2/Tests/Files/ClosingTagUnitTest.5.inc | 1 + .../Files/ClosingTagUnitTest.5.inc.fixed | 1 + .../PSR2/Tests/Files/ClosingTagUnitTest.6.inc | 5 + .../Files/ClosingTagUnitTest.6.inc.fixed | 5 + .../PSR2/Tests/Files/ClosingTagUnitTest.7.inc | 5 + .../Files/ClosingTagUnitTest.7.inc.fixed | 5 + .../PSR2/Tests/Files/ClosingTagUnitTest.php | 64 + .../Tests/Files/EndFileNewlineUnitTest.1.inc | 3 + .../Files/EndFileNewlineUnitTest.1.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.10.inc | 3 + .../Files/EndFileNewlineUnitTest.10.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.11.inc | 1 + .../Files/EndFileNewlineUnitTest.11.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.12.inc | 1 + .../Files/EndFileNewlineUnitTest.12.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.13.inc | 5 + .../Files/EndFileNewlineUnitTest.13.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.14.inc | 1 + .../Tests/Files/EndFileNewlineUnitTest.2.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.inc | 2 + .../Files/EndFileNewlineUnitTest.3.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.4.inc | 4 + .../Tests/Files/EndFileNewlineUnitTest.5.inc | 6 + .../Tests/Files/EndFileNewlineUnitTest.6.inc | 2 + .../Files/EndFileNewlineUnitTest.6.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.7.inc | 11 + .../Files/EndFileNewlineUnitTest.7.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.8.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.9.inc | 2 + .../Files/EndFileNewlineUnitTest.9.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.php | 66 + .../Methods/FunctionCallSignatureUnitTest.inc | 267 ++ .../FunctionCallSignatureUnitTest.inc.fixed | 283 ++ .../Methods/FunctionCallSignatureUnitTest.php | 94 + .../Methods/FunctionClosingBraceUnitTest.inc | 70 + .../FunctionClosingBraceUnitTest.inc.fixed | 61 + .../Methods/FunctionClosingBraceUnitTest.php | 55 + .../Methods/MethodDeclarationUnitTest.inc | 75 + .../MethodDeclarationUnitTest.inc.fixed | 75 + .../Methods/MethodDeclarationUnitTest.php | 71 + .../NamespaceDeclarationUnitTest.inc | 26 + .../NamespaceDeclarationUnitTest.inc.fixed | 28 + .../NamespaceDeclarationUnitTest.php | 53 + .../Namespaces/UseDeclarationUnitTest.1.inc | 43 + .../Namespaces/UseDeclarationUnitTest.10.inc | 8 + .../UseDeclarationUnitTest.10.inc.fixed | 9 + .../Namespaces/UseDeclarationUnitTest.11.inc | 2 + .../UseDeclarationUnitTest.11.inc.fixed | 4 + .../Namespaces/UseDeclarationUnitTest.12.inc | 9 + .../UseDeclarationUnitTest.12.inc.fixed | 11 + .../Namespaces/UseDeclarationUnitTest.13.inc | 10 + .../UseDeclarationUnitTest.13.inc.fixed | 11 + .../Namespaces/UseDeclarationUnitTest.14.inc | 8 + .../UseDeclarationUnitTest.14.inc.fixed | 9 + .../Namespaces/UseDeclarationUnitTest.15.inc | 10 + .../Namespaces/UseDeclarationUnitTest.16.inc | 11 + .../UseDeclarationUnitTest.16.inc.fixed | 9 + .../Namespaces/UseDeclarationUnitTest.17.inc | 3 + .../Namespaces/UseDeclarationUnitTest.2.inc | 21 + .../UseDeclarationUnitTest.2.inc.fixed | 27 + .../Namespaces/UseDeclarationUnitTest.3.inc | 16 + .../UseDeclarationUnitTest.3.inc.fixed | 16 + .../Namespaces/UseDeclarationUnitTest.4.inc | 4 + .../Namespaces/UseDeclarationUnitTest.5.inc | 47 + .../UseDeclarationUnitTest.5.inc.fixed | 56 + .../Namespaces/UseDeclarationUnitTest.6.inc | 1 + .../Namespaces/UseDeclarationUnitTest.7.inc | 1 + .../Namespaces/UseDeclarationUnitTest.8.inc | 8 + .../Namespaces/UseDeclarationUnitTest.9.inc | 8 + .../Namespaces/UseDeclarationUnitTest.php | 97 + .../src/Standards/PSR2/ruleset.xml | 218 + .../Arrays/ArrayBracketSpacingStandard.xml | 19 + .../Docs/Arrays/ArrayDeclarationStandard.xml | 117 + .../LowercaseClassKeywordsStandard.xml | 23 + .../Classes/SelfMemberReferenceStandard.xml | 63 + .../DocCommentAlignmentStandard.xml | 39 + .../FunctionCommentThrowTagStandard.xml | 32 + .../ForEachLoopDeclarationStandard.xml | 39 + .../ForLoopDeclarationStandard.xml | 55 + .../LowercaseDeclarationStandard.xml | 23 + .../FunctionDuplicateArgumentStandard.xml | 23 + .../LowercaseFunctionKeywordsStandard.xml | 25 + .../Docs/Scope/StaticThisUsageStandard.xml | 31 + .../Docs/Strings/EchoedStringsStandard.xml | 19 + .../Docs/WhiteSpace/CastSpacingStandard.xml | 19 + .../FunctionOpeningBraceStandard.xml | 41 + .../LanguageConstructSpacingStandard.xml | 19 + .../ObjectOperatorSpacingStandard.xml | 19 + .../ScopeKeywordSpacingStandard.xml | 23 + .../WhiteSpace/SemicolonSpacingStandard.xml | 19 + .../Arrays/ArrayBracketSpacingSniff.php | 95 + .../Sniffs/Arrays/ArrayDeclarationSniff.php | 895 ++++ .../ClassDefinitionClosingBraceSpaceSniff.php | 134 + .../CSS/ClassDefinitionNameSpacingSniff.php | 111 + .../ClassDefinitionOpeningBraceSpaceSniff.php | 176 + .../Squiz/Sniffs/CSS/ColonSpacingSniff.php | 107 + .../Sniffs/CSS/ColourDefinitionSniff.php | 88 + .../DisallowMultipleStyleDefinitionsSniff.php | 71 + .../CSS/DuplicateClassDefinitionSniff.php | 116 + .../CSS/DuplicateStyleDefinitionSniff.php | 88 + .../Sniffs/CSS/EmptyClassDefinitionSniff.php | 61 + .../Sniffs/CSS/EmptyStyleDefinitionSniff.php | 64 + .../Squiz/Sniffs/CSS/ForbiddenStylesSniff.php | 177 + .../Squiz/Sniffs/CSS/IndentationSniff.php | 150 + .../CSS/LowercaseStyleDefinitionSniff.php | 97 + .../Squiz/Sniffs/CSS/MissingColonSniff.php | 91 + .../Squiz/Sniffs/CSS/NamedColoursSniff.php | 93 + .../Squiz/Sniffs/CSS/OpacitySniff.php | 101 + .../Sniffs/CSS/SemicolonSpacingSniff.php | 103 + .../Squiz/Sniffs/CSS/ShorthandSizeSniff.php | 181 + .../Sniffs/Classes/ClassDeclarationSniff.php | 206 + .../Sniffs/Classes/ClassFileNameSniff.php | 70 + .../Sniffs/Classes/DuplicatePropertySniff.php | 82 + .../Classes/LowercaseClassKeywordsSniff.php | 72 + .../Classes/SelfMemberReferenceSniff.php | 240 ++ .../Sniffs/Classes/ValidClassNameSniff.php | 87 + .../Sniffs/Commenting/BlockCommentSniff.php | 401 ++ .../Sniffs/Commenting/ClassCommentSniff.php | 106 + .../ClosingDeclarationCommentSniff.php | 132 + .../Commenting/DocCommentAlignmentSniff.php | 161 + .../Commenting/EmptyCatchCommentSniff.php | 55 + .../Sniffs/Commenting/FileCommentSniff.php | 227 + .../Commenting/FunctionCommentSniff.php | 768 ++++ .../FunctionCommentThrowTagSniff.php | 233 + .../Sniffs/Commenting/InlineCommentSniff.php | 348 ++ .../LongConditionClosingCommentSniff.php | 218 + .../Commenting/PostStatementCommentSniff.php | 121 + .../Commenting/VariableCommentSniff.php | 193 + .../ControlSignatureSniff.php | 325 ++ .../ElseIfDeclarationSniff.php | 51 + .../ForEachLoopDeclarationSniff.php | 236 ++ .../ForLoopDeclarationSniff.php | 316 ++ .../InlineIfDeclarationSniff.php | 155 + .../LowercaseDeclarationSniff.php | 75 + .../SwitchDeclarationSniff.php | 304 ++ .../Squiz/Sniffs/Debug/JSLintSniff.php | 86 + .../Sniffs/Debug/JavaScriptLintSniff.php | 89 + .../Squiz/Sniffs/Files/FileExtensionSniff.php | 68 + .../Formatting/OperatorBracketSniff.php | 393 ++ ...unctionDeclarationArgumentSpacingSniff.php | 398 ++ .../Functions/FunctionDeclarationSniff.php | 34 + .../FunctionDuplicateArgumentSniff.php | 64 + .../Sniffs/Functions/GlobalFunctionSniff.php | 61 + .../LowercaseFunctionKeywordsSniff.php | 69 + .../MultiLineFunctionDeclarationSniff.php | 258 ++ .../ValidFunctionNameSniff.php | 54 + .../ValidVariableNameSniff.php | 190 + .../DisallowObjectStringIndexSniff.php | 85 + .../Objects/ObjectInstantiationSniff.php | 85 + .../Sniffs/Objects/ObjectMemberCommaSniff.php | 64 + .../ComparisonOperatorUsageSniff.php | 235 ++ .../IncrementDecrementUsageSniff.php | 225 + .../Operators/ValidLogicalOperatorsSniff.php | 67 + .../Sniffs/PHP/CommentedOutCodeSniff.php | 288 ++ .../PHP/DisallowBooleanStatementSniff.php | 59 + .../PHP/DisallowComparisonAssignmentSniff.php | 111 + .../Sniffs/PHP/DisallowInlineIfSniff.php | 57 + .../PHP/DisallowMultipleAssignmentsSniff.php | 186 + .../PHP/DisallowSizeFunctionsInLoopsSniff.php | 116 + .../Sniffs/PHP/DiscouragedFunctionsSniff.php | 38 + .../Squiz/Sniffs/PHP/EmbeddedPhpSniff.php | 402 ++ .../Standards/Squiz/Sniffs/PHP/EvalSniff.php | 48 + .../Squiz/Sniffs/PHP/GlobalKeywordSniff.php | 53 + .../Squiz/Sniffs/PHP/HeredocSniff.php | 51 + .../Squiz/Sniffs/PHP/InnerFunctionsSniff.php | 68 + .../Sniffs/PHP/LowercasePHPFunctionsSniff.php | 162 + .../Sniffs/PHP/NonExecutableCodeSniff.php | 277 ++ .../Sniffs/Scope/MemberVarScopeSniff.php | 77 + .../Squiz/Sniffs/Scope/MethodScopeSniff.php | 83 + .../Sniffs/Scope/StaticThisUsageSniff.php | 128 + .../Strings/ConcatenationSpacingSniff.php | 164 + .../Sniffs/Strings/DoubleQuoteUsageSniff.php | 144 + .../Sniffs/Strings/EchoedStringsSniff.php | 88 + .../Sniffs/WhiteSpace/CastSpacingSniff.php | 65 + .../ControlStructureSpacingSniff.php | 359 ++ .../FunctionClosingBraceSpaceSniff.php | 164 + .../FunctionOpeningBraceSpaceSniff.php | 98 + .../WhiteSpace/FunctionSpacingSniff.php | 367 ++ .../LanguageConstructSpacingSniff.php | 89 + .../LogicalOperatorSpacingSniff.php | 102 + .../WhiteSpace/MemberVarSpacingSniff.php | 254 ++ .../WhiteSpace/ObjectOperatorSpacingSniff.php | 167 + .../WhiteSpace/OperatorSpacingSniff.php | 381 ++ .../WhiteSpace/PropertyLabelSpacingSniff.php | 79 + .../WhiteSpace/ScopeClosingBraceSniff.php | 114 + .../WhiteSpace/ScopeKeywordSpacingSniff.php | 169 + .../WhiteSpace/SemicolonSpacingSniff.php | 116 + .../WhiteSpace/SuperfluousWhitespaceSniff.php | 265 ++ .../Arrays/ArrayBracketSpacingUnitTest.inc | 31 + .../ArrayBracketSpacingUnitTest.inc.fixed | 31 + .../Arrays/ArrayBracketSpacingUnitTest.php | 57 + .../Arrays/ArrayDeclarationUnitTest.1.inc | 488 +++ .../ArrayDeclarationUnitTest.1.inc.fixed | 524 +++ .../Arrays/ArrayDeclarationUnitTest.2.inc | 470 +++ .../ArrayDeclarationUnitTest.2.inc.fixed | 504 +++ .../Tests/Arrays/ArrayDeclarationUnitTest.php | 236 ++ ...assDefinitionClosingBraceSpaceUnitTest.css | 81 + ...initionClosingBraceSpaceUnitTest.css.fixed | 85 + ...assDefinitionClosingBraceSpaceUnitTest.php | 60 + .../ClassDefinitionNameSpacingUnitTest.css | 66 + .../ClassDefinitionNameSpacingUnitTest.php | 51 + ...assDefinitionOpeningBraceSpaceUnitTest.css | 108 + ...initionOpeningBraceSpaceUnitTest.css.fixed | 106 + ...assDefinitionOpeningBraceSpaceUnitTest.php | 64 + .../Squiz/Tests/CSS/ColonSpacingUnitTest.css | 42 + .../Tests/CSS/ColonSpacingUnitTest.css.fixed | 40 + .../Squiz/Tests/CSS/ColonSpacingUnitTest.php | 60 + .../Tests/CSS/ColourDefinitionUnitTest.css | 16 + .../CSS/ColourDefinitionUnitTest.css.fixed | 16 + .../Tests/CSS/ColourDefinitionUnitTest.php | 52 + ...sallowMultipleStyleDefinitionsUnitTest.css | 17 + ...MultipleStyleDefinitionsUnitTest.css.fixed | 27 + ...sallowMultipleStyleDefinitionsUnitTest.php | 54 + .../CSS/DuplicateClassDefinitionUnitTest.css | 103 + .../CSS/DuplicateClassDefinitionUnitTest.php | 54 + .../CSS/DuplicateStyleDefinitionUnitTest.css | 27 + .../CSS/DuplicateStyleDefinitionUnitTest.php | 48 + .../CSS/EmptyClassDefinitionUnitTest.css | 15 + .../CSS/EmptyClassDefinitionUnitTest.php | 54 + .../CSS/EmptyStyleDefinitionUnitTest.css | 11 + .../CSS/EmptyStyleDefinitionUnitTest.php | 53 + .../Tests/CSS/ForbiddenStylesUnitTest.css | 18 + .../CSS/ForbiddenStylesUnitTest.css.fixed | 18 + .../Tests/CSS/ForbiddenStylesUnitTest.php | 57 + .../Squiz/Tests/CSS/IndentationUnitTest.1.css | 79 + .../Tests/CSS/IndentationUnitTest.1.css.fixed | 73 + .../Squiz/Tests/CSS/IndentationUnitTest.2.css | 3 + .../Squiz/Tests/CSS/IndentationUnitTest.php | 75 + .../CSS/LowercaseStyleDefinitionUnitTest.css | 14 + .../CSS/LowercaseStyleDefinitionUnitTest.php | 53 + .../Squiz/Tests/CSS/MissingColonUnitTest.css | 21 + .../Squiz/Tests/CSS/MissingColonUnitTest.php | 53 + .../Squiz/Tests/CSS/NamedColoursUnitTest.css | 25 + .../Squiz/Tests/CSS/NamedColoursUnitTest.php | 54 + .../Squiz/Tests/CSS/OpacityUnitTest.css | 35 + .../Squiz/Tests/CSS/OpacityUnitTest.css.fixed | 35 + .../Squiz/Tests/CSS/OpacityUnitTest.php | 60 + .../Tests/CSS/SemicolonSpacingUnitTest.css | 61 + .../CSS/SemicolonSpacingUnitTest.css.fixed | 58 + .../Tests/CSS/SemicolonSpacingUnitTest.php | 58 + .../Squiz/Tests/CSS/ShorthandSizeUnitTest.css | 45 + .../Tests/CSS/ShorthandSizeUnitTest.css.fixed | 41 + .../Squiz/Tests/CSS/ShorthandSizeUnitTest.php | 59 + .../Classes/ClassDeclarationUnitTest.inc | 121 + .../ClassDeclarationUnitTest.inc.fixed | 132 + .../Classes/ClassDeclarationUnitTest.php | 84 + .../Tests/Classes/ClassFileNameUnitTest.inc | 45 + .../Tests/Classes/ClassFileNameUnitTest.php | 77 + .../Classes/DuplicatePropertyUnitTest.js | 45 + .../Classes/DuplicatePropertyUnitTest.php | 52 + .../LowercaseClassKeywordsUnitTest.inc | 14 + .../LowercaseClassKeywordsUnitTest.inc.fixed | 14 + .../LowercaseClassKeywordsUnitTest.php | 59 + .../Classes/SelfMemberReferenceUnitTest.inc | 174 + .../SelfMemberReferenceUnitTest.inc.fixed | 162 + .../Classes/SelfMemberReferenceUnitTest.php | 64 + .../Tests/Classes/ValidClassNameUnitTest.inc | 191 + .../Tests/Classes/ValidClassNameUnitTest.php | 75 + .../Tests/Commenting/BlockCommentUnitTest.inc | 309 ++ .../Commenting/BlockCommentUnitTest.inc.fixed | 311 ++ .../Tests/Commenting/BlockCommentUnitTest.php | 104 + .../Tests/Commenting/ClassCommentUnitTest.inc | 133 + .../Tests/Commenting/ClassCommentUnitTest.php | 59 + .../ClosingDeclarationCommentUnitTest.inc | 86 + .../ClosingDeclarationCommentUnitTest.php | 58 + .../DocCommentAlignmentUnitTest.inc | 103 + .../DocCommentAlignmentUnitTest.inc.fixed | 103 + .../Commenting/DocCommentAlignmentUnitTest.js | 76 + .../DocCommentAlignmentUnitTest.js.fixed | 76 + .../DocCommentAlignmentUnitTest.php | 76 + .../Commenting/EmptyCatchCommentUnitTest.inc | 55 + .../Commenting/EmptyCatchCommentUnitTest.php | 55 + .../Commenting/FileCommentUnitTest.1.inc | 43 + .../FileCommentUnitTest.1.inc.fixed | 43 + .../Tests/Commenting/FileCommentUnitTest.1.js | 40 + .../Commenting/FileCommentUnitTest.1.js.fixed | 40 + .../Commenting/FileCommentUnitTest.2.inc | 11 + .../Tests/Commenting/FileCommentUnitTest.2.js | 10 + .../Commenting/FileCommentUnitTest.3.inc | 9 + .../Commenting/FileCommentUnitTest.4.inc | 3 + .../Commenting/FileCommentUnitTest.5.inc | 4 + .../Commenting/FileCommentUnitTest.6.inc | 12 + .../Commenting/FileCommentUnitTest.7.inc | 12 + .../Commenting/FileCommentUnitTest.8.inc | 9 + .../Commenting/FileCommentUnitTest.9.inc | 12 + .../Tests/Commenting/FileCommentUnitTest.php | 76 + .../FunctionCommentThrowTagUnitTest.inc | 511 +++ .../FunctionCommentThrowTagUnitTest.php | 60 + .../Commenting/FunctionCommentUnitTest.inc | 1048 +++++ .../FunctionCommentUnitTest.inc.fixed | 1048 +++++ .../Commenting/FunctionCommentUnitTest.php | 177 + .../Commenting/InlineCommentUnitTest.inc | 183 + .../InlineCommentUnitTest.inc.fixed | 176 + .../Tests/Commenting/InlineCommentUnitTest.js | 129 + .../Commenting/InlineCommentUnitTest.js.fixed | 125 + .../Commenting/InlineCommentUnitTest.php | 91 + .../LongConditionClosingCommentUnitTest.inc | 1033 +++++ ...gConditionClosingCommentUnitTest.inc.fixed | 1033 +++++ .../LongConditionClosingCommentUnitTest.js | 444 ++ ...ngConditionClosingCommentUnitTest.js.fixed | 444 ++ .../LongConditionClosingCommentUnitTest.php | 103 + .../PostStatementCommentUnitTest.1.js | 36 + .../PostStatementCommentUnitTest.1.js.fixed | 39 + .../PostStatementCommentUnitTest.2.js | 2 + .../PostStatementCommentUnitTest.inc | 54 + .../PostStatementCommentUnitTest.inc.fixed | 59 + .../PostStatementCommentUnitTest.php | 69 + .../Commenting/VariableCommentUnitTest.inc | 404 ++ .../VariableCommentUnitTest.inc.fixed | 404 ++ .../Commenting/VariableCommentUnitTest.php | 83 + .../ControlSignatureUnitTest.inc | 310 ++ .../ControlSignatureUnitTest.inc.fixed | 314 ++ .../ControlSignatureUnitTest.js | 135 + .../ControlSignatureUnitTest.js.fixed | 141 + .../ControlSignatureUnitTest.php | 102 + .../ElseIfDeclarationUnitTest.inc | 14 + .../ElseIfDeclarationUnitTest.inc.fixed | 14 + .../ElseIfDeclarationUnitTest.php | 51 + .../ForEachLoopDeclarationUnitTest.inc | 36 + .../ForEachLoopDeclarationUnitTest.inc.fixed | 36 + .../ForEachLoopDeclarationUnitTest.php | 56 + .../ForLoopDeclarationUnitTest.inc | 129 + .../ForLoopDeclarationUnitTest.inc.fixed | 95 + .../ForLoopDeclarationUnitTest.js | 125 + .../ForLoopDeclarationUnitTest.js.fixed | 91 + .../ForLoopDeclarationUnitTest.php | 132 + .../InlineIfDeclarationUnitTest.inc | 48 + .../InlineIfDeclarationUnitTest.inc.fixed | 48 + .../InlineIfDeclarationUnitTest.php | 75 + .../LowercaseDeclarationUnitTest.inc | 24 + .../LowercaseDeclarationUnitTest.inc.fixed | 24 + .../LowercaseDeclarationUnitTest.php | 61 + .../SwitchDeclarationUnitTest.inc | 333 ++ .../SwitchDeclarationUnitTest.inc.fixed | 342 ++ .../SwitchDeclarationUnitTest.js | 287 ++ .../SwitchDeclarationUnitTest.php | 152 + .../Squiz/Tests/Debug/JSLintUnitTest.js | 2 + .../Squiz/Tests/Debug/JSLintUnitTest.php | 69 + .../Tests/Debug/JavaScriptLintUnitTest.js | 2 + .../Tests/Debug/JavaScriptLintUnitTest.php | 66 + .../Tests/Files/FileExtensionUnitTest.1.inc | 3 + .../Tests/Files/FileExtensionUnitTest.2.inc | 3 + .../Tests/Files/FileExtensionUnitTest.3.inc | 3 + .../Tests/Files/FileExtensionUnitTest.4.inc | 3 + .../Tests/Files/FileExtensionUnitTest.5.inc | 3 + .../Tests/Files/FileExtensionUnitTest.php | 55 + .../Formatting/OperatorBracketUnitTest.inc | 195 + .../OperatorBracketUnitTest.inc.fixed | 195 + .../Formatting/OperatorBracketUnitTest.js | 118 + .../OperatorBracketUnitTest.js.fixed | 118 + .../Formatting/OperatorBracketUnitTest.php | 117 + ...tionDeclarationArgumentSpacingUnitTest.inc | 111 + ...clarationArgumentSpacingUnitTest.inc.fixed | 111 + ...tionDeclarationArgumentSpacingUnitTest.php | 86 + .../Functions/FunctionDeclarationUnitTest.inc | 75 + .../Functions/FunctionDeclarationUnitTest.php | 51 + .../FunctionDuplicateArgumentUnitTest.inc | 6 + .../FunctionDuplicateArgumentUnitTest.php | 52 + .../Functions/GlobalFunctionUnitTest.inc | 17 + .../Functions/GlobalFunctionUnitTest.php | 48 + .../LowercaseFunctionKeywordsUnitTest.inc | 28 + ...owercaseFunctionKeywordsUnitTest.inc.fixed | 28 + .../LowercaseFunctionKeywordsUnitTest.php | 58 + .../MultiLineFunctionDeclarationUnitTest.inc | 257 ++ ...iLineFunctionDeclarationUnitTest.inc.fixed | 269 ++ .../MultiLineFunctionDeclarationUnitTest.js | 73 + ...tiLineFunctionDeclarationUnitTest.js.fixed | 81 + .../MultiLineFunctionDeclarationUnitTest.php | 113 + .../ValidFunctionNameUnitTest.inc | 27 + .../ValidFunctionNameUnitTest.php | 59 + .../ValidVariableNameUnitTest.inc | 157 + .../ValidVariableNameUnitTest.php | 88 + .../DisallowObjectStringIndexUnitTest.js | 37 + .../DisallowObjectStringIndexUnitTest.php | 59 + .../Objects/ObjectInstantiationUnitTest.inc | 46 + .../Objects/ObjectInstantiationUnitTest.php | 53 + .../Objects/ObjectMemberCommaUnitTest.js | 47 + .../ObjectMemberCommaUnitTest.js.fixed | 47 + .../Objects/ObjectMemberCommaUnitTest.php | 53 + .../ComparisonOperatorUsageUnitTest.inc | 138 + .../ComparisonOperatorUsageUnitTest.js | 71 + .../ComparisonOperatorUsageUnitTest.php | 101 + .../IncrementDecrementUsageUnitTest.inc | 42 + .../IncrementDecrementUsageUnitTest.php | 60 + .../ValidLogicalOperatorsUnitTest.inc | 28 + .../ValidLogicalOperatorsUnitTest.php | 52 + .../Tests/PHP/CommentedOutCodeUnitTest.css | 23 + .../Tests/PHP/CommentedOutCodeUnitTest.inc | 158 + .../Tests/PHP/CommentedOutCodeUnitTest.php | 76 + .../PHP/DisallowBooleanStatementUnitTest.inc | 27 + .../PHP/DisallowBooleanStatementUnitTest.php | 53 + .../DisallowComparisonAssignmentUnitTest.inc | 73 + .../DisallowComparisonAssignmentUnitTest.php | 59 + .../Tests/PHP/DisallowInlineIfUnitTest.inc | 18 + .../Tests/PHP/DisallowInlineIfUnitTest.js | 2 + .../Tests/PHP/DisallowInlineIfUnitTest.php | 63 + .../DisallowMultipleAssignmentsUnitTest.inc | 110 + .../DisallowMultipleAssignmentsUnitTest.php | 58 + .../DisallowSizeFunctionsInLoopsUnitTest.inc | 58 + .../DisallowSizeFunctionsInLoopsUnitTest.js | 13 + .../DisallowSizeFunctionsInLoopsUnitTest.php | 73 + .../PHP/DiscouragedFunctionsUnitTest.inc | 5 + .../PHP/DiscouragedFunctionsUnitTest.php | 52 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc | 119 + .../Tests/PHP/EmbeddedPhpUnitTest.inc.fixed | 119 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.php | 78 + .../Squiz/Tests/PHP/EvalUnitTest.inc | 5 + .../Squiz/Tests/PHP/EvalUnitTest.php | 51 + .../Squiz/Tests/PHP/GlobalKeywordUnitTest.inc | 13 + .../Squiz/Tests/PHP/GlobalKeywordUnitTest.php | 51 + .../Squiz/Tests/PHP/HeredocUnitTest.inc | 27 + .../Squiz/Tests/PHP/HeredocUnitTest.php | 51 + .../Tests/PHP/InnerFunctionsUnitTest.inc | 50 + .../Tests/PHP/InnerFunctionsUnitTest.php | 51 + .../PHP/LowercasePHPFunctionsUnitTest.inc | 43 + .../LowercasePHPFunctionsUnitTest.inc.fixed | 43 + .../PHP/LowercasePHPFunctionsUnitTest.php | 55 + .../Tests/PHP/NonExecutableCodeUnitTest.1.inc | 301 ++ .../Tests/PHP/NonExecutableCodeUnitTest.2.inc | 61 + .../Tests/PHP/NonExecutableCodeUnitTest.php | 97 + .../Tests/Scope/MemberVarScopeUnitTest.inc | 72 + .../Tests/Scope/MemberVarScopeUnitTest.php | 57 + .../Squiz/Tests/Scope/MethodScopeUnitTest.inc | 57 + .../Squiz/Tests/Scope/MethodScopeUnitTest.php | 53 + .../Tests/Scope/StaticThisUsageUnitTest.inc | 127 + .../Tests/Scope/StaticThisUsageUnitTest.php | 62 + .../Strings/ConcatenationSpacingUnitTest.inc | 49 + .../ConcatenationSpacingUnitTest.inc.fixed | 47 + .../Strings/ConcatenationSpacingUnitTest.php | 66 + .../Strings/DoubleQuoteUsageUnitTest.inc | 37 + .../DoubleQuoteUsageUnitTest.inc.fixed | 37 + .../Strings/DoubleQuoteUsageUnitTest.php | 62 + .../Tests/Strings/EchoedStringsUnitTest.inc | 13 + .../Strings/EchoedStringsUnitTest.inc.fixed | 13 + .../Tests/Strings/EchoedStringsUnitTest.php | 55 + .../Tests/WhiteSpace/CastSpacingUnitTest.inc | 9 + .../WhiteSpace/CastSpacingUnitTest.inc.fixed | 9 + .../Tests/WhiteSpace/CastSpacingUnitTest.php | 54 + .../ControlStructureSpacingUnitTest.inc | 269 ++ .../ControlStructureSpacingUnitTest.inc.fixed | 261 ++ .../ControlStructureSpacingUnitTest.js | 93 + .../ControlStructureSpacingUnitTest.js.fixed | 93 + .../ControlStructureSpacingUnitTest.php | 103 + .../FunctionClosingBraceSpaceUnitTest.inc | 39 + ...unctionClosingBraceSpaceUnitTest.inc.fixed | 45 + .../FunctionClosingBraceSpaceUnitTest.js | 132 + ...FunctionClosingBraceSpaceUnitTest.js.fixed | 133 + .../FunctionClosingBraceSpaceUnitTest.php | 76 + .../FunctionOpeningBraceSpaceUnitTest.inc | 54 + ...unctionOpeningBraceSpaceUnitTest.inc.fixed | 49 + .../FunctionOpeningBraceSpaceUnitTest.js | 115 + ...FunctionOpeningBraceSpaceUnitTest.js.fixed | 109 + .../FunctionOpeningBraceSpaceUnitTest.php | 68 + .../WhiteSpace/FunctionSpacingUnitTest.1.inc | 576 +++ .../FunctionSpacingUnitTest.1.inc.fixed | 658 +++ .../WhiteSpace/FunctionSpacingUnitTest.2.inc | 5 + .../FunctionSpacingUnitTest.2.inc.fixed | 7 + .../WhiteSpace/FunctionSpacingUnitTest.3.inc | 10 + .../FunctionSpacingUnitTest.3.inc.fixed | 7 + .../WhiteSpace/FunctionSpacingUnitTest.4.inc | 7 + .../WhiteSpace/FunctionSpacingUnitTest.5.inc | 8 + .../FunctionSpacingUnitTest.5.inc.fixed | 10 + .../WhiteSpace/FunctionSpacingUnitTest.6.inc | 13 + .../FunctionSpacingUnitTest.6.inc.fixed | 10 + .../WhiteSpace/FunctionSpacingUnitTest.7.inc | 10 + .../WhiteSpace/FunctionSpacingUnitTest.php | 134 + .../LanguageConstructSpacingUnitTest.inc | 43 + ...LanguageConstructSpacingUnitTest.inc.fixed | 41 + .../LanguageConstructSpacingUnitTest.php | 60 + .../LogicalOperatorSpacingUnitTest.inc | 19 + .../LogicalOperatorSpacingUnitTest.inc.fixed | 19 + .../LogicalOperatorSpacingUnitTest.js | 19 + .../LogicalOperatorSpacingUnitTest.js.fixed | 19 + .../LogicalOperatorSpacingUnitTest.php | 56 + .../WhiteSpace/MemberVarSpacingUnitTest.inc | 374 ++ .../MemberVarSpacingUnitTest.inc.fixed | 359 ++ .../WhiteSpace/MemberVarSpacingUnitTest.php | 85 + .../ObjectOperatorSpacingUnitTest.inc | 52 + .../ObjectOperatorSpacingUnitTest.inc.fixed | 48 + .../ObjectOperatorSpacingUnitTest.php | 68 + .../WhiteSpace/OperatorSpacingUnitTest.inc | 481 +++ .../OperatorSpacingUnitTest.inc.fixed | 475 +++ .../WhiteSpace/OperatorSpacingUnitTest.js | 103 + .../OperatorSpacingUnitTest.js.fixed | 97 + .../WhiteSpace/OperatorSpacingUnitTest.php | 170 + .../PropertyLabelSpacingUnitTest.js | 40 + .../PropertyLabelSpacingUnitTest.js.fixed | 39 + .../PropertyLabelSpacingUnitTest.php | 55 + .../WhiteSpace/ScopeClosingBraceUnitTest.inc | 134 + .../ScopeClosingBraceUnitTest.inc.fixed | 138 + .../WhiteSpace/ScopeClosingBraceUnitTest.php | 59 + .../ScopeKeywordSpacingUnitTest.inc | 141 + .../ScopeKeywordSpacingUnitTest.inc.fixed | 135 + .../ScopeKeywordSpacingUnitTest.php | 70 + .../WhiteSpace/SemicolonSpacingUnitTest.inc | 42 + .../SemicolonSpacingUnitTest.inc.fixed | 41 + .../WhiteSpace/SemicolonSpacingUnitTest.js | 25 + .../SemicolonSpacingUnitTest.js.fixed | 25 + .../WhiteSpace/SemicolonSpacingUnitTest.php | 83 + .../SuperfluousWhitespaceUnitTest.1.css | 25 + .../SuperfluousWhitespaceUnitTest.1.css.fixed | 23 + .../SuperfluousWhitespaceUnitTest.1.inc | 74 + .../SuperfluousWhitespaceUnitTest.1.inc.fixed | 68 + .../SuperfluousWhitespaceUnitTest.1.js | 56 + .../SuperfluousWhitespaceUnitTest.1.js.fixed | 50 + .../SuperfluousWhitespaceUnitTest.2.css | 3 + .../SuperfluousWhitespaceUnitTest.2.css.fixed | 3 + .../SuperfluousWhitespaceUnitTest.2.inc | 9 + .../SuperfluousWhitespaceUnitTest.2.inc.fixed | 7 + .../SuperfluousWhitespaceUnitTest.2.js | 1 + .../SuperfluousWhitespaceUnitTest.2.js.fixed | 1 + .../SuperfluousWhitespaceUnitTest.3.css | 3 + .../SuperfluousWhitespaceUnitTest.3.css.fixed | 3 + .../SuperfluousWhitespaceUnitTest.3.inc | 14 + .../SuperfluousWhitespaceUnitTest.3.inc.fixed | 5 + .../SuperfluousWhitespaceUnitTest.3.js | 1 + .../SuperfluousWhitespaceUnitTest.3.js.fixed | 1 + .../SuperfluousWhitespaceUnitTest.4.inc | 4 + .../SuperfluousWhitespaceUnitTest.4.inc.fixed | 4 + .../SuperfluousWhitespaceUnitTest.5.inc | 5 + .../SuperfluousWhitespaceUnitTest.5.inc.fixed | 4 + .../SuperfluousWhitespaceUnitTest.php | 113 + .../src/Standards/Squiz/ruleset.xml | 132 + .../Zend/Docs/Debug/CodeAnalyzerStandard.xml | 25 + .../Zend/Docs/Files/ClosingTagStandard.xml | 22 + .../ValidVariableNameStandard.xml | 37 + .../Zend/Sniffs/Debug/CodeAnalyzerSniff.php | 98 + .../Zend/Sniffs/Files/ClosingTagSniff.php | 79 + .../ValidVariableNameSniff.php | 196 + .../Zend/Tests/Debug/CodeAnalyzerUnitTest.inc | 6 + .../Zend/Tests/Debug/CodeAnalyzerUnitTest.php | 66 + .../Zend/Tests/Files/ClosingTagUnitTest.1.inc | 12 + .../Files/ClosingTagUnitTest.1.inc.fixed | 12 + .../Zend/Tests/Files/ClosingTagUnitTest.2.inc | 3 + .../Zend/Tests/Files/ClosingTagUnitTest.3.inc | 1 + .../Files/ClosingTagUnitTest.3.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.4.inc | 1 + .../Files/ClosingTagUnitTest.4.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.5.inc | 1 + .../Files/ClosingTagUnitTest.5.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.6.inc | 3 + .../Files/ClosingTagUnitTest.6.inc.fixed | 3 + .../Zend/Tests/Files/ClosingTagUnitTest.7.inc | 1 + .../Files/ClosingTagUnitTest.7.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.php | 65 + .../ValidVariableNameUnitTest.inc | 131 + .../ValidVariableNameUnitTest.php | 96 + .../src/Standards/Zend/ruleset.xml | 32 + .../php_codesniffer/src/Tokenizers/CSS.php | 537 +++ .../src/Tokenizers/Comment.php | 277 ++ .../php_codesniffer/src/Tokenizers/JS.php | 1256 ++++++ .../php_codesniffer/src/Tokenizers/PHP.php | 3484 +++++++++++++++ .../src/Tokenizers/Tokenizer.php | 1732 ++++++++ .../php_codesniffer/src/Util/Cache.php | 351 ++ .../php_codesniffer/src/Util/Common.php | 570 +++ .../php_codesniffer/src/Util/Standards.php | 339 ++ .../php_codesniffer/src/Util/Timing.php | 86 + .../php_codesniffer/src/Util/Tokens.php | 809 ++++ .../php_codesniffer/tests/AllTests.php | 64 + .../tests/Core/AbstractMethodUnitTest.php | 140 + .../php_codesniffer/tests/Core/AllTests.php | 63 + .../Autoloader/DetermineLoadedClassTest.php | 118 + .../tests/Core/Autoloader/TestFiles/A.inc | 3 + .../tests/Core/Autoloader/TestFiles/B.inc | 4 + .../tests/Core/Autoloader/TestFiles/C.inc | 4 + .../tests/Core/Autoloader/TestFiles/Sub/C.inc | 5 + .../tests/Core/ErrorSuppressionTest.php | 1247 ++++++ .../Core/File/FindEndOfStatementTest.inc | 105 + .../Core/File/FindEndOfStatementTest.php | 415 ++ .../Core/File/FindExtendedClassNameTest.inc | 37 + .../Core/File/FindExtendedClassNameTest.php | 93 + .../FindImplementedInterfaceNamesTest.inc | 35 + .../FindImplementedInterfaceNamesTest.php | 104 + .../Core/File/FindStartOfStatementTest.inc | 123 + .../Core/File/FindStartOfStatementTest.php | 503 +++ .../Core/File/GetMemberPropertiesTest.inc | 304 ++ .../Core/File/GetMemberPropertiesTest.php | 864 ++++ .../Core/File/GetMethodParametersTest.inc | 164 + .../Core/File/GetMethodParametersTest.php | 1145 +++++ .../Core/File/GetMethodPropertiesTest.inc | 152 + .../Core/File/GetMethodPropertiesTest.php | 911 ++++ .../tests/Core/File/IsReferenceTest.inc | 150 + .../tests/Core/File/IsReferenceTest.php | 248 ++ .../tests/Core/Filters/Filter/AcceptTest.php | 154 + .../tests/Core/Filters/Filter/AcceptTest.xml | 16 + .../tests/Core/IsCamelCapsTest.php | 135 + .../RuleInclusionAbsoluteLinuxTest.php | 118 + .../RuleInclusionAbsoluteLinuxTest.xml | 11 + .../RuleInclusionAbsoluteWindowsTest.php | 119 + .../RuleInclusionAbsoluteWindowsTest.xml | 11 + .../Ruleset/RuleInclusionTest-include.xml | 10 + .../tests/Core/Ruleset/RuleInclusionTest.php | 297 ++ .../tests/Core/Ruleset/RuleInclusionTest.xml | 46 + .../Core/Sniffs/AbstractArraySniffTest.inc | 51 + .../Core/Sniffs/AbstractArraySniffTest.php | 290 ++ .../Sniffs/AbstractArraySniffTestable.php | 65 + .../AnonClassParenthesisOwnerTest.inc | 19 + .../AnonClassParenthesisOwnerTest.php | 144 + .../tests/Core/Tokenizer/ArrayKeywordTest.inc | 35 + .../tests/Core/Tokenizer/ArrayKeywordTest.php | 170 + .../tests/Core/Tokenizer/AttributesTest.inc | 90 + .../tests/Core/Tokenizer/AttributesTest.php | 659 +++ .../tests/Core/Tokenizer/BackfillEnumTest.inc | 95 + .../tests/Core/Tokenizer/BackfillEnumTest.php | 229 + .../BackfillExplicitOctalNotationTest.inc | 28 + .../BackfillExplicitOctalNotationTest.php | 114 + .../Core/Tokenizer/BackfillFnTokenTest.inc | 198 + .../Core/Tokenizer/BackfillFnTokenTest.php | 802 ++++ .../Core/Tokenizer/BackfillMatchTokenTest.inc | 319 ++ .../Core/Tokenizer/BackfillMatchTokenTest.php | 529 +++ .../BackfillNumericSeparatorTest.inc | 94 + .../BackfillNumericSeparatorTest.php | 420 ++ .../Core/Tokenizer/BackfillReadonlyTest.inc | 100 + .../Core/Tokenizer/BackfillReadonlyTest.php | 236 ++ .../tests/Core/Tokenizer/BitwiseOrTest.inc | 134 + .../tests/Core/Tokenizer/BitwiseOrTest.php | 138 + .../ContextSensitiveKeywordsTest.inc | 227 + .../ContextSensitiveKeywordsTest.php | 509 +++ .../Core/Tokenizer/DefaultKeywordTest.inc | 203 + .../Core/Tokenizer/DefaultKeywordTest.php | 302 ++ .../tests/Core/Tokenizer/DoubleArrowTest.inc | 281 ++ .../tests/Core/Tokenizer/DoubleArrowTest.php | 237 ++ .../Core/Tokenizer/DoubleQuotedStringTest.inc | 52 + .../Core/Tokenizer/DoubleQuotedStringTest.php | 136 + .../tests/Core/Tokenizer/EnumCaseTest.inc | 95 + .../tests/Core/Tokenizer/EnumCaseTest.php | 157 + .../tests/Core/Tokenizer/FinallyTest.inc | 40 + .../tests/Core/Tokenizer/FinallyTest.php | 96 + .../tests/Core/Tokenizer/GotoLabelTest.inc | 56 + .../tests/Core/Tokenizer/GotoLabelTest.php | 175 + .../NamedFunctionCallArgumentsTest.inc | 404 ++ .../NamedFunctionCallArgumentsTest.php | 884 ++++ .../Tokenizer/NullsafeObjectOperatorTest.inc | 29 + .../Tokenizer/NullsafeObjectOperatorTest.php | 140 + .../ScopeSettingWithNamespaceOperatorTest.inc | 19 + .../ScopeSettingWithNamespaceOperatorTest.php | 98 + .../tests/Core/Tokenizer/ShortArrayTest.inc | 97 + .../tests/Core/Tokenizer/ShortArrayTest.php | 132 + .../Tokenizer/StableCommentWhitespaceTest.inc | 139 + .../Tokenizer/StableCommentWhitespaceTest.php | 1056 +++++ .../StableCommentWhitespaceWinTest.inc | 63 + .../StableCommentWhitespaceWinTest.php | 367 ++ .../Core/Tokenizer/TypeIntersectionTest.inc | 120 + .../Core/Tokenizer/TypeIntersectionTest.php | 138 + .../UndoNamespacedNameSingleTokenTest.inc | 147 + .../UndoNamespacedNameSingleTokenTest.php | 1295 ++++++ .../php_codesniffer/tests/FileList.php | 94 + .../tests/Standards/AbstractSniffUnitTest.php | 461 ++ .../tests/Standards/AllSniffs.php | 123 + .../php_codesniffer/tests/TestSuite.php | 35 + .../php_codesniffer/tests/TestSuite7.php | 35 + .../php_codesniffer/tests/bootstrap.php | 91 + .../wp-coding-standards/wpcs/.gitattributes | 25 + .../wp-coding-standards/wpcs/.gitignore | 5 + .../wp-coding-standards/wpcs/CHANGELOG.md | 1208 ++++++ .../wp-coding-standards/wpcs/LICENSE | 21 + .../wp-coding-standards/wpcs/README.md | 296 ++ .../wpcs/WordPress-Core/ruleset.xml | 529 +++ .../wpcs/WordPress-Docs/ruleset.xml | 109 + .../wpcs/WordPress-Extra/ruleset.xml | 187 + ...stractArrayAssignmentRestrictionsSniff.php | 240 ++ .../AbstractClassRestrictionsSniff.php | 245 ++ .../AbstractFunctionParameterSniff.php | 112 + .../AbstractFunctionRestrictionsSniff.php | 342 ++ .../Docs/Arrays/ArrayIndentationStandard.xml | 112 + .../ArrayKeySpacingRestrictionsStandard.xml | 27 + .../MultipleStatementAlignmentStandard.xml | 46 + .../Classes/ClassInstantiationStandard.xml | 53 + .../EscapedNotTranslatedStandard.xml | 20 + .../DateTime/CurrentTimeTimestampStandard.xml | 31 + .../ValidHookNameStandard.xml | 32 + .../ValidPostTypeSlugStandard.xml | 117 + .../Docs/PHP/DisallowShortTernaryStandard.xml | 20 + .../WordPress/Docs/PHP/IniSetStandard.xml | 36 + .../Docs/Security/SafeRedirectStandard.xml | 19 + .../Docs/WP/CronIntervalStandard.xml | 41 + .../Docs/WP/DeprecatedClassesStandard.xml | 19 + .../Docs/WP/DeprecatedFunctionsStandard.xml | 19 + .../WP/DeprecatedParameterValuesStandard.xml | 19 + .../Docs/WP/DeprecatedParametersStandard.xml | 36 + .../Docs/WP/EnqueuedResourcesStandard.xml | 53 + .../Docs/WP/PostsPerPageStandard.xml | 69 + .../CastStructureSpacingStandard.xml | 23 + .../WhiteSpace/DisallowInlineTabsStandard.xml | 25 + .../WhiteSpace/PrecisionAlignmentStandard.xml | 31 + .../wpcs/WordPress/PHPCSHelper.php | 109 + .../wpcs/WordPress/Sniff.php | 3424 +++++++++++++++ .../Arrays/ArrayDeclarationSpacingSniff.php | 468 ++ .../Sniffs/Arrays/ArrayIndentationSniff.php | 542 +++ .../ArrayKeySpacingRestrictionsSniff.php | 192 + .../Arrays/CommaAfterArrayItemSniff.php | 313 ++ .../MultipleStatementAlignmentSniff.php | 617 +++ .../Classes/ClassInstantiationSniff.php | 204 + .../AssignmentInConditionSniff.php | 235 ++ .../CodeAnalysis/EmptyStatementSniff.php | 161 + .../EscapedNotTranslatedSniff.php | 90 + .../Sniffs/DB/DirectDatabaseQuerySniff.php | 265 ++ .../DB/PreparedSQLPlaceholdersSniff.php | 661 +++ .../WordPress/Sniffs/DB/PreparedSQLSniff.php | 210 + .../Sniffs/DB/RestrictedClassesSniff.php | 60 + .../Sniffs/DB/RestrictedFunctionsSniff.php | 66 + .../WordPress/Sniffs/DB/SlowDBQuerySniff.php | 86 + .../DateTime/CurrentTimeTimestampSniff.php | 174 + .../DateTime/RestrictedFunctionsSniff.php | 62 + .../WordPress/Sniffs/Files/FileNameSniff.php | 248 ++ .../PrefixAllGlobalsSniff.php | 1046 +++++ .../ValidFunctionNameSniff.php | 187 + .../NamingConventions/ValidHookNameSniff.php | 289 ++ .../ValidPostTypeSlugSniff.php | 208 + .../ValidVariableNameSniff.php | 299 ++ .../Sniffs/PHP/DevelopmentFunctionsSniff.php | 66 + .../Sniffs/PHP/DisallowShortTernarySniff.php | 65 + .../PHP/DiscouragedPHPFunctionsSniff.php | 103 + .../WordPress/Sniffs/PHP/DontExtractSniff.php | 55 + .../wpcs/WordPress/Sniffs/PHP/IniSetSniff.php | 177 + .../Sniffs/PHP/NoSilencedErrorsSniff.php | 239 ++ .../Sniffs/PHP/POSIXFunctionsSniff.php | 76 + .../Sniffs/PHP/PregQuoteDelimiterSniff.php | 69 + .../PHP/RestrictedPHPFunctionsSniff.php | 48 + .../Sniffs/PHP/StrictComparisonsSniff.php | 56 + .../Sniffs/PHP/StrictInArraySniff.php | 105 + .../WordPress/Sniffs/PHP/TypeCastsSniff.php | 99 + .../Sniffs/PHP/YodaConditionsSniff.php | 125 + .../Sniffs/Security/EscapeOutputSniff.php | 505 +++ .../Security/NonceVerificationSniff.php | 178 + .../Sniffs/Security/PluginMenuSlugSniff.php | 89 + .../Sniffs/Security/SafeRedirectSniff.php | 48 + .../Security/ValidatedSanitizedInputSniff.php | 233 + .../Sniffs/Utils/I18nTextDomainFixerSniff.php | 731 ++++ .../Sniffs/WP/AlternativeFunctionsSniff.php | 316 ++ .../Sniffs/WP/CapitalPDangitSniff.php | 292 ++ .../WordPress/Sniffs/WP/CronIntervalSniff.php | 235 ++ .../Sniffs/WP/DeprecatedClassesSniff.php | 120 + .../Sniffs/WP/DeprecatedFunctionsSniff.php | 1422 +++++++ .../WP/DeprecatedParameterValuesSniff.php | 216 + .../Sniffs/WP/DeprecatedParametersSniff.php | 338 ++ .../Sniffs/WP/DiscouragedConstantsSniff.php | 217 + .../Sniffs/WP/DiscouragedFunctionsSniff.php | 57 + .../WP/EnqueuedResourceParametersSniff.php | 223 + .../Sniffs/WP/EnqueuedResourcesSniff.php | 64 + .../WP/GlobalVariablesOverrideSniff.php | 466 ++ .../wpcs/WordPress/Sniffs/WP/I18nSniff.php | 789 ++++ .../WordPress/Sniffs/WP/PostsPerPageSniff.php | 78 + .../Sniffs/WP/TimezoneChangeSniff.php | 88 + .../WhiteSpace/CastStructureSpacingSniff.php | 62 + .../ControlStructureSpacingSniff.php | 572 +++ .../WhiteSpace/DisallowInlineTabsSniff.php | 104 + .../WhiteSpace/OperatorSpacingSniff.php | 64 + .../WhiteSpace/PrecisionAlignmentSniff.php | 199 + .../wpcs/WordPress/ruleset.xml | 17 + .../wp-coding-standards/wpcs/composer.json | 56 + .../wpcs/phpcs.xml.dist.sample | 92 + .../wptrt/wpthemereview/CHANGELOG.md | 114 + .../wptrt/wpthemereview/LICENSE.txt | 21 + kirki-composer/wptrt/wpthemereview/README.md | 118 + .../CoreFunctionality/FileIncludeSniff.php | 69 + .../NoDeregisterCoreScriptSniff.php | 234 + .../CoreFunctionality/NoFaviconSniff.php | 117 + .../CoreFunctionality/NoTitleTagSniff.php | 103 + .../CoreFunctionality/PostsPerPageSniff.php | 51 + .../PrefixAllGlobalsSniff.php | 191 + .../PluginTerritory/AdminBarRemovalSniff.php | 417 ++ .../ForbiddenFunctionsSniff.php | 77 + .../PluginTerritory/NoAddAdminPagesSniff.php | 66 + .../SessionFunctionsUsageSniff.php | 79 + .../SessionVariableUsageSniff.php | 66 + .../Plugins/CorrectTGMPAVersionSniff.php | 546 +++ .../Sniffs/Privacy/ShortenedURLsSniff.php | 150 + .../Templates/ReservedFileNamePrefixSniff.php | 170 + .../ThouShallNotUse/ForbiddenIframeSniff.php | 67 + .../ThouShallNotUse/NoAutoGenerateSniff.php | 99 + .../wpthemereview/WPThemeReview/ruleset.xml | 171 + .../wptrt/wpthemereview/composer.json | 90 + .../compatibility/LICENSE | 0 .../compatibility/src/Aliases.php | 0 .../compatibility/src/Config.php | 0 .../compatibility/src/Control.php | 0 .../compatibility/src/Deprecated.php | 0 .../compatibility/src/Field.php | 0 .../compatibility/src/Framework.php | 0 .../compatibility/src/Init.php | 0 .../compatibility/src/Kirki.php | 0 .../compatibility/src/Modules.php | 0 .../compatibility/src/Sanitize_Values.php | 0 .../compatibility/src/Scripts.php | 0 .../compatibility/src/Settings.php | 0 .../compatibility/src/Values.php | 0 .../compatibility/src/deprecated/classes.php | 0 .../compatibility/src/deprecated/filters.php | 0 .../src/deprecated/functions.php | 0 .../compatibility/src/scripts/hooks.js | 0 .../compatibility/src/scripts/i18n.js | 0 .../compatibility/src/scripts/wp-polyfill.js | 0 .../control-base/LICENSE | 0 .../control-base/dist/control.css | 0 .../control-base/dist/control.css.map | 0 .../control-base/dist/control.js | 0 .../control-base/dist/control.js.map | 0 .../control-base/src/Control/Base.php | 0 .../control-base/src/control.js | 0 .../control-base/src/control.scss | 0 .../control-base/src/dynamic-control.js | 0 .../control-base/src/rtl.scss | 0 .../control-checkbox/LICENSE | 0 .../control-checkbox/dist/control.css | 0 .../control-checkbox/dist/control.css.map | 0 .../control-checkbox/dist/control.js | 0 .../control-checkbox/dist/control.js.map | 0 .../control-checkbox/src/Control/Checkbox.php | 0 .../src/Control/Checkbox_Switch.php | 0 .../src/Control/Checkbox_Toggle.php | 0 .../control-checkbox/src/Field/Checkbox.php | 0 .../src/Field/Checkbox_Switch.php | 0 .../src/Field/Checkbox_Toggle.php | 0 .../control-checkbox/src/control.js | 0 .../control-checkbox/src/control.scss | 0 .../control-checkbox/src/scss/_vars.scss | 0 .../control-code/LICENSE | 0 .../control-code/src/Control/Code.php | 0 .../control-code/src/Field/Code.php | 0 .../control-color-palette/dist/control.css | 0 .../dist/control.css.map | 0 .../control-color-palette/dist/control.js | 0 .../control-color-palette/dist/control.js.map | 0 .../src/Control/Color_Palette.php | 0 .../src/Field/Color_Palette.php | 0 .../src/KirkiColorPaletteControl.js | 0 .../src/KirkiColorPaletteForm.js | 0 .../control-color-palette/src/control.js | 0 .../control-color-palette/src/control.scss | 0 .../control-color/LICENSE | 0 .../control-color/src/Field/Color.php | 0 .../control-cropped-image/LICENSE | 0 .../src/Cropped_Image.php | 0 .../control-custom/LICENSE | 0 .../control-custom/src/Control/Custom.php | 0 .../control-custom/src/Field/Custom.php | 0 .../control-dashicons/LICENSE | 0 .../control-dashicons/dist/control.css | 0 .../control-dashicons/dist/control.css.map | 0 .../control-dashicons/dist/control.js | 0 .../control-dashicons/dist/control.js.map | 0 .../src/Control/Dashicons.php | 0 .../control-dashicons/src/Field/Dashicons.php | 0 .../control-dashicons/src/Util/Dashicons.php | 0 .../control-dashicons/src/control.js | 0 .../control-dashicons/src/control.scss | 0 .../control-date/LICENSE | 0 .../control-date/dist/control.css | 0 .../control-date/dist/control.css.map | 0 .../control-date/dist/control.js | 0 .../control-date/dist/control.js.map | 0 .../control-date/src/Control/Date.php | 0 .../control-date/src/Field/Date.php | 0 .../control-date/src/control.js | 0 .../control-date/src/control.scss | 0 .../control-dimension/LICENSE | 0 .../control-dimension/dist/control.css | 0 .../control-dimension/dist/control.css.map | 0 .../control-dimension/dist/control.js | 0 .../control-dimension/dist/control.js.map | 0 .../src/Control/Dimension.php | 0 .../control-dimension/src/Field/Dimension.php | 0 .../control-dimension/src/control.js | 0 .../control-dimension/src/control.scss | 0 .../control-editor/LICENSE | 0 .../control-editor/dist/control.css | 0 .../control-editor/dist/control.css.map | 0 .../control-editor/dist/control.js | 0 .../control-editor/dist/control.js.map | 0 .../control-editor/src/Control/Editor.php | 0 .../control-editor/src/Field/Editor.php | 0 .../control-editor/src/control.js | 0 .../control-editor/src/control.scss | 0 .../control-generic/LICENSE | 0 .../control-generic/dist/control.js | 0 .../control-generic/dist/control.js.map | 0 .../control-generic/src/Control/Generic.php | 0 .../control-generic/src/Field/Generic.php | 0 .../control-generic/src/Field/Number.php | 0 .../control-generic/src/Field/Text.php | 0 .../control-generic/src/Field/Textarea.php | 0 .../control-generic/src/Field/URL.php | 0 .../control-generic/src/control.js | 0 .../control-generic/src/control.scss | 0 .../control-image/LICENSE | 0 .../control-image/dist/control.js | 0 .../control-image/dist/control.js.map | 0 .../control-image/src/Control/Image.php | 0 .../control-image/src/Field/CSS/Image.php | 0 .../control-image/src/Field/Image.php | 0 .../control-image/src/control.js | 0 .../control-multicheck/LICENSE | 0 .../control-multicheck/dist/control.css | 0 .../control-multicheck/dist/control.css.map | 0 .../control-multicheck/dist/control.js | 0 .../control-multicheck/dist/control.js.map | 0 .../src/Control/Multicheck.php | 0 .../src/Field/Multicheck.php | 0 .../control-multicheck/src/control.js | 0 .../control-multicheck/src/control.scss | 0 .../control-palette/LICENSE | 0 .../control-palette/dist/control.css | 0 .../control-palette/dist/control.css.map | 0 .../control-palette/dist/control.js | 0 .../control-palette/dist/control.js.map | 0 .../control-palette/src/Control/Palette.php | 0 .../control-palette/src/Field/Palette.php | 0 .../control-palette/src/control.js | 0 .../control-palette/src/control.scss | 0 .../control-radio/LICENSE | 0 .../control-radio/dist/control.css | 0 .../control-radio/dist/control.css.map | 0 .../control-radio/dist/control.js | 0 .../control-radio/dist/control.js.map | 0 .../control-radio/src/Control/Radio.php | 0 .../src/Control/Radio_Buttonset.php | 0 .../control-radio/src/Control/Radio_Image.php | 0 .../control-radio/src/Field/Radio.php | 0 .../src/Field/Radio_Buttonset.php | 0 .../control-radio/src/Field/Radio_Image.php | 0 .../control-radio/src/control.js | 0 .../control-radio/src/control.scss | 0 .../src/scss/_radio-buttonset.scss | 0 .../control-radio/src/scss/_radio-image.scss | 0 .../control-radio/src/scss/_radio.scss | 0 .../control-react-colorful/LICENSE | 0 .../control-react-colorful/dist/control.css | 0 .../dist/control.css.map | 0 .../control-react-colorful/dist/control.js | 0 .../dist/control.js.map | 0 .../control-react-colorful/dist/preview.js | 0 .../dist/preview.js.map | 0 .../src/Control/ReactColorful.php | 0 .../src/Field/CSS/ReactColorful.php | 0 .../src/Field/ReactColorful.php | 0 .../src/KirkiReactColorfulControl.js | 0 .../src/KirkiReactColorfulForm.js | 0 .../control-react-colorful/src/control.js | 0 .../control-react-colorful/src/control.scss | 0 .../js/components/KirkiReactColorfulCircle.js | 0 .../js/components/KirkiReactColorfulInput.js | 0 .../components/KirkiReactColorfulSwatches.js | 0 .../src/js/hooks/useClickOutside.js | 0 .../src/js/hooks/useFocusOutside.js | 0 .../src/js/hooks/useWindowResize.js | 0 .../src/js/utils/convertColorForCustomizer.js | 0 .../src/js/utils/convertColorForInput.js | 0 .../src/js/utils/convertColorForPicker.js | 0 .../src/js/utils/util.js | 0 .../control-react-colorful/src/preview.js | 0 .../control-react-select/LICENSE | 0 .../control-react-select/dist/control.css | 0 .../control-react-select/dist/control.css.map | 0 .../control-react-select/dist/control.js | 0 .../dist/control.js.LICENSE.txt | 0 .../control-react-select/dist/control.js.map | 0 .../src/Control/ReactSelect.php | 0 .../src/Field/ReactSelect.php | 0 .../src/KirkiSelectControl.js | 0 .../src/KirkiSelectForm.js | 0 .../control-react-select/src/control.js | 0 .../control-react-select/src/control.scss | 0 .../control-repeater/LICENSE | 0 .../control-repeater/dist/control.css | 0 .../control-repeater/dist/control.css.map | 0 .../control-repeater/dist/control.js | 0 .../control-repeater/dist/control.js.map | 0 .../dist/wp-color-picker-alpha.min.js | 0 .../control-repeater/src/Control/Repeater.php | 0 .../control-repeater/src/Field/Repeater.php | 0 .../src/Settings/Repeater.php | 0 .../control-repeater/src/control.js | 0 .../control-repeater/src/control.scss | 0 .../src/Field/Dropdown_Pages.php | 0 .../control-select/src/Field/Preset.php | 0 .../control-select/src/Field/Select.php | 0 .../control-slider/dist/control.css | 0 .../control-slider/dist/control.css.map | 0 .../control-slider/dist/control.js | 0 .../control-slider/dist/control.js.map | 0 .../control-slider/src/Control/Slider.php | 0 .../control-slider/src/Field/Slider.php | 0 .../control-slider/src/KirkiSliderControl.js | 0 .../control-slider/src/KirkiSliderForm.js | 0 .../control-slider/src/control.js | 0 .../control-slider/src/control.scss | 0 .../control-sortable/LICENSE | 0 .../control-sortable/dist/control.css | 0 .../control-sortable/dist/control.css.map | 0 .../control-sortable/dist/control.js | 0 .../control-sortable/dist/control.js.map | 0 .../control-sortable/src/Control/Sortable.php | 0 .../control-sortable/src/Field/Sortable.php | 0 .../control-sortable/src/control.js | 0 .../control-sortable/src/control.scss | 0 .../control-upload/LICENSE | 0 .../control-upload/src/Control/Upload.php | 0 .../control-upload/src/Field/Upload.php | 0 .../data-option/LICENSE | 0 .../data-option/src/Option.php | 0 .../field-background/LICENSE | 0 .../field-background/src/Background.php | 0 .../field-background/src/CSS/Background.php | 0 .../field-background/src/script.js | 0 .../field-dimensions/LICENSE | 0 .../field-dimensions/dist/control.css | 0 .../field-dimensions/dist/control.css.map | 0 .../field-dimensions/dist/preview.js | 0 .../field-dimensions/dist/preview.js.map | 0 .../field-dimensions/src/CSS/Dimensions.php | 0 .../field-dimensions/src/Dimensions.php | 0 .../field-dimensions/src/control.scss | 0 .../field-dimensions/src/preview.js | 0 .../field-fontawesome/LICENSE | 0 .../src/Field/FontAwesome.php | 0 .../src/Field/fontawesome.json | 0 .../field-multicolor/LICENSE | 0 .../src/Field/CSS/Multicolor.php | 0 .../field-multicolor/src/Field/Multicolor.php | 0 .../field-typography/LICENSE | 0 .../field-typography/dist/control.css | 0 .../field-typography/dist/control.css.map | 0 .../field-typography/dist/control.js | 0 .../field-typography/dist/control.js.map | 0 .../field-typography/dist/preview.js | 0 .../field-typography/dist/preview.js.map | 0 .../src/Field/CSS/Typography.php | 0 .../field-typography/src/Field/Typography.php | 0 .../field-typography/src/control.js | 0 .../field-typography/src/control.scss | 0 .../field-typography/src/preview.js | 0 {packages => kirki-packages}/field/LICENSE | 0 .../field/src/Field.php | 2 +- .../field/src/Field/None.php | 0 .../googlefonts/Gruntfile.js | 0 .../googlefonts/LICENSE | 0 .../googlefonts/src/GoogleFonts.php | 0 .../googlefonts/src/webfont-files.json | 0 .../googlefonts/src/webfont-names.json | 0 .../googlefonts/src/webfonts.json | 0 {packages => kirki-packages}/l10n/LICENSE | 0 .../l10n/src/L10n.php | 0 .../module-css/LICENSE | 0 .../module-css/src/CSS.php | 0 .../module-css/src/CSS/Generator.php | 0 .../module-css/src/CSS/Output.php | 0 .../module-css/src/CSS/Property.php | 0 .../src/CSS/Property/Background_Image.php | 0 .../src/CSS/Property/Background_Position.php | 0 .../src/CSS/Property/Font_Family.php | 0 .../module-editor-styles/LICENSE | 0 .../src/Editor_Styles.php | 0 .../module-field-dependencies/LICENSE | 0 .../module-field-dependencies/dist/control.js | 0 .../dist/control.js.map | 0 .../src/Field_Dependencies.php | 0 .../module-field-dependencies/src/control.js | 0 .../module-panels/LICENSE | 0 .../module-panels/src/Panel.php | 0 .../module-panels/src/Panel_Types/Nested.php | 0 .../module-panels/src/script.js | 0 .../module-postmessage/LICENSE | 0 .../module-postmessage/src/Postmessage.php | 0 .../module-postmessage/src/postMessage.js | 0 .../module-preset/LICENSE | 0 .../module-preset/src/Preset.php | 0 .../module-preset/src/script.js | 0 .../module-section-icons/LICENSE | 0 .../src/Section_Icons.php | 0 .../module-section-icons/src/icons.js | 0 .../module-sections/LICENSE | 0 .../module-sections/src/Section.php | 0 .../src/Section_Types/Expanded.php | 0 .../src/Section_Types/Link.php | 0 .../src/Section_Types/Nested.php | 0 .../src/Section_Types/Outer.php | 0 .../module-sections/src/script.js | 0 .../module-sections/src/styles.css | 0 .../module-selective-refresh/LICENSE | 0 .../src/Selective_Refresh.php | 0 .../module-tooltips/LICENSE | 0 .../module-tooltips/dist/control.css | 0 .../module-tooltips/dist/control.css.map | 0 .../module-tooltips/dist/control.js | 0 .../module-tooltips/dist/control.js.map | 0 .../module-tooltips/src/Tooltips.php | 0 .../module-tooltips/src/control.js | 0 .../module-tooltips/src/control.scss | 0 .../module-webfonts/LICENSE | 0 .../module-webfonts/src/Webfonts.php | 0 .../module-webfonts/src/Webfonts/Async.php | 0 .../src/Webfonts/Downloader.php | 0 .../module-webfonts/src/Webfonts/Embed.php | 0 .../module-webfonts/src/Webfonts/Fonts.php | 0 .../module-webfonts/src/Webfonts/Google.php | 0 .../scripts/vendor-typekit/src/closure.js | 0 .../vendor-typekit/src/core/cssclassname.js | 0 .../vendor-typekit/src/core/domhelper.js | 0 .../src/core/eventdispatcher.js | 0 .../scripts/vendor-typekit/src/core/font.js | 0 .../vendor-typekit/src/core/fontmodule.js | 0 .../src/core/fontmoduleloader.js | 0 .../vendor-typekit/src/core/fontruler.js | 0 .../vendor-typekit/src/core/fontwatcher.js | 0 .../src/core/fontwatchrunner.js | 0 .../vendor-typekit/src/core/initialize.js | 0 .../src/core/nativefontwatchrunner.js | 0 .../src/core/stylesheetwaiter.js | 0 .../vendor-typekit/src/core/webfont.js | 0 .../scripts/vendor-typekit/src/modules.yml | 0 .../vendor-typekit/src/modules/custom.js | 0 .../vendor-typekit/src/modules/fontdeck.js | 0 .../src/modules/google/fontapiparser.js | 0 .../src/modules/google/fontapiurlbuilder.js | 0 .../src/modules/google/googlefontapi.js | 0 .../vendor-typekit/src/modules/monotype.js | 0 .../vendor-typekit/src/modules/typekit.js | 0 .../scripts/vendor-typekit/webfontloader.js | 0 .../settings/dist/admin-notice.css | 0 .../settings/dist/admin-notice.css.map | 1 + .../settings/dist/discount-notice.js | 0 .../settings/dist/discount-notice.js.map | 1 + .../settings/dist/heatbox.css | 0 .../settings/dist/settings.css | 0 kirki-packages/settings/dist/settings.css.map | 1 + .../settings/dist/settings.js | 0 kirki-packages/settings/dist/settings.js.map | 1 + .../settings/src/Notice.php | 4 +- .../settings/src/SetupSettings.php | 8 +- .../settings/src/admin-notice.scss | 0 .../settings/src/discount-notice.ts | 0 .../settings/src/settings.scss | 0 .../settings/src/settings.ts | 0 .../settings/src/setup-udb.ts | 0 .../settings/src/tabs.ts | 0 .../settings/src/utils.ts | 0 .../templates/metaboxes/clear-font-cache.php | 0 .../templates/metaboxes/documentation.php | 0 .../metaboxes/installation-progress.php | 0 .../metaboxes/recommended-plugins.php | 0 .../metaboxes/ultimate-dashboard.php | 0 .../settings/templates/settings-template.php | 0 .../url-getter/LICENSE | 0 .../url-getter/src/URL.php | 0 {packages => kirki-packages}/util/LICENSE | 0 .../util/src/Helper.php | 0 .../util/src/MaterialColors.php | 0 .../util/src/Setting/Site_Option.php | 0 .../util/src/Setting/User_Meta.php | 0 .../util/src/Util.php | 0 kirki.mjs | 46 +- packages/settings/dist/admin-notice.css.map | 1 - packages/settings/dist/discount-notice.js.map | 1 - packages/settings/dist/settings.css.map | 1 - packages/settings/dist/settings.js.map | 1 - vendor/composer/autoload_psr4.php | 18 - vendor/composer/autoload_static.php | 125 - 2264 files changed, 233467 insertions(+), 239 deletions(-) rename {vendor => kirki-composer}/autoload.php (91%) create mode 100644 kirki-composer/bin/phpcbf create mode 100644 kirki-composer/bin/phpcbf.bat create mode 100644 kirki-composer/bin/phpcs create mode 100644 kirki-composer/bin/phpcs.bat rename {vendor => kirki-composer}/composer/ClassLoader.php (100%) rename {vendor => kirki-composer}/composer/InstalledVersions.php (100%) rename {vendor => kirki-composer}/composer/LICENSE (100%) rename {vendor => kirki-composer}/composer/autoload_classmap.php (100%) rename {vendor => kirki-composer}/composer/autoload_namespaces.php (100%) create mode 100644 kirki-composer/composer/autoload_psr4.php rename {vendor => kirki-composer}/composer/autoload_real.php (67%) create mode 100644 kirki-composer/composer/autoload_static.php rename {vendor => kirki-composer}/composer/include_paths.php (100%) rename {vendor => kirki-composer}/composer/installed.json (100%) rename {vendor => kirki-composer}/composer/installed.php (100%) create mode 100644 kirki-composer/composer/installers/.github/workflows/continuous-integration.yml create mode 100644 kirki-composer/composer/installers/.github/workflows/lint.yml create mode 100644 kirki-composer/composer/installers/.github/workflows/phpstan.yml create mode 100644 kirki-composer/composer/installers/LICENSE create mode 100644 kirki-composer/composer/installers/composer.json create mode 100644 kirki-composer/composer/installers/phpstan.neon.dist create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/AglInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/AkauntingInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/AsgardInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/AttogramInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/BaseInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/BitrixInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/BonefishInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/CakePHPInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ChefInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/CiviCrmInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/CockpitInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/Concrete5Installer.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/CroogoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/DecibelInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/DframeInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/DokuWikiInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/DolibarrInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/DrupalInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ElggInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/EliasisInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/EzPlatformInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/FuelInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/FuelphpInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/GravInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/HuradInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ImageCMSInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/Installer.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ItopInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/KanboardInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/KnownInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/KodiCMSInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/KohanaInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/LaravelInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/LavaLiteInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/LithiumInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MODXEvoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MagentoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MajimaInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MakoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MantisBTInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MatomoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MauticInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MayaInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MediaWikiInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MiaoxingInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MicroweberInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ModxInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/MoodleInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/OctoberInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/OntoWikiInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/OsclassInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/OxidInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PPIInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PantheonInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PhiftyInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PhpBBInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PiwikInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/Plugin.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PortoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PrestashopInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ProcessWireInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PuppetInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/PxcmsInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/RadPHPInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ReIndexInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/Redaxo5Installer.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/RedaxoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/RoundcubeInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/SMFInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ShopwareInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/SilverStripeInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/SiteDirectInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/StarbugInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/SyDESInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/SyliusInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/TaoInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/TastyIgniterInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/TheliaInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/TuskInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/UserFrostingInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/VanillaInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/VgmcpInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/WHMCSInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/WinterInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/WolfCMSInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/WordPressInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/YawikInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ZendInstaller.php create mode 100644 kirki-composer/composer/installers/src/Composer/Installers/ZikulaInstaller.php create mode 100644 kirki-composer/composer/installers/src/bootstrap.php rename {vendor => kirki-composer}/composer/platform_check.php (100%) create mode 100644 kirki-composer/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md create mode 100644 kirki-composer/dealerdirect/phpcodesniffer-composer-installer/README.md create mode 100644 kirki-composer/dealerdirect/phpcodesniffer-composer-installer/composer.json create mode 100644 kirki-composer/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/CHANGELOG.md create mode 100644 kirki-composer/phpcompatibility/php-compatibility/LICENSE create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCSAliases.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/PHPCSHelper.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php create mode 100644 kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml create mode 100644 kirki-composer/phpcompatibility/php-compatibility/README.md create mode 100644 kirki-composer/phpcompatibility/php-compatibility/composer.json create mode 100644 kirki-composer/phpcompatibility/php-compatibility/phpunit-bootstrap.php create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-paragonie/LICENSE create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-paragonie/README.md create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-paragonie/composer.json create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-wp/LICENSE create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-wp/README.md create mode 100644 kirki-composer/phpcompatibility/phpcompatibility-wp/composer.json create mode 100644 kirki-composer/squizlabs/php_codesniffer/CONTRIBUTING.md create mode 100644 kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf create mode 100644 kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf.dist create mode 100644 kirki-composer/squizlabs/php_codesniffer/README.md create mode 100644 kirki-composer/squizlabs/php_codesniffer/autoload.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/bin/phpcbf create mode 100644 kirki-composer/squizlabs/php_codesniffer/bin/phpcbf.bat create mode 100644 kirki-composer/squizlabs/php_codesniffer/bin/phpcs create mode 100644 kirki-composer/squizlabs/php_codesniffer/bin/phpcs.bat create mode 100644 kirki-composer/squizlabs/php_codesniffer/composer.json create mode 100644 kirki-composer/squizlabs/php_codesniffer/licence.txt create mode 100644 kirki-composer/squizlabs/php_codesniffer/phpcs.xsd create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Config.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Files/DummyFile.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Files/File.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Files/FileList.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Files/LocalFile.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Filters/ExactMatch.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Filters/Filter.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Filters/GitModified.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Filters/GitStaged.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Fixer.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Generators/Generator.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Generators/HTML.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Generators/Markdown.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Generators/Text.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reporter.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Cbf.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Checkstyle.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Code.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Csv.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Diff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Emacs.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Full.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Gitblame.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Hgblame.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Info.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Json.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Junit.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Notifysend.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Report.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Source.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Summary.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Svnblame.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/VersionControl.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Reports/Xml.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Ruleset.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Runner.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Sniffs/Sniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowRequestSuperglobalSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowShortOpenTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DiscourageGotoSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ForbiddenFunctionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/LowerCaseConstantSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/LowerCaseTypeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/NoSilencedErrorsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/RequireStrictTypesSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/SAPIUsageSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/SyntaxSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/UpperCaseConstantSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Strings/UnnecessaryStringConcatSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/VersionControl/GitMergeConflictSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/VersionControl/SubversionPropertiesSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/ArbitraryParenthesesSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/IncrementDecrementSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/SpreadOperatorSpacingAfterSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowShortArraySyntaxUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowShortArraySyntaxUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowShortArraySyntaxUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/OpeningBraceSameLineUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/OpeningBraceSameLineUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/OpeningBraceSameLineUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyPHPStatementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyPHPStatementUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyPHPStatementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyStatementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyStatementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/FixmeUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/FixmeUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/FixmeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/TodoUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/TodoUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/TodoUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/DisallowYodaConditionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/DisallowYodaConditionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/CSSLintUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/CSSLintUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ClosureLinterUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ClosureLinterUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ESLintUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ESLintUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/JSHintUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/JSHintUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.4.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.6.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.7.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.10.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.6.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.8.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.9.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.9.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneClassPerFileUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneClassPerFileUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneInterfacePerFileUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneInterfacePerFileUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneObjectStructurePerFileUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneObjectStructurePerFileUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneTraitPerFileUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneTraitPerFileUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceBeforeCastUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceBeforeCastUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceBeforeCastUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/CyclomaticComplexityUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/CyclomaticComplexityUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/NestingLevelUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/NestingLevelUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/AbstractClassNamePrefixUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/AbstractClassNamePrefixUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/ConstructorNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/ConstructorNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/InterfaceNameSuffixUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/InterfaceNameSuffixUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/TraitNameSuffixUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/TraitNameSuffixUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/UpperCaseConstantNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/UpperCaseConstantNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/BacktickOperatorUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/BacktickOperatorUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DeprecatedFunctionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DeprecatedFunctionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.11.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.12.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.13.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.9.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.10.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.10.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.11.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.11.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.12.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.12.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.13.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.14.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.17.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.4.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.7.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.9.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.10.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.10.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.11.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.11.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.14.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.6.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.7.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.9.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.9.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.10.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.10.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.11.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.11.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.12.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.12.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.13.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.13.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.14.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.14.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.15.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.16.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.16.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.17.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.9.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.5.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.6.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.2.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/CSS.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Comment.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/JS.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/PHP.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Util/Cache.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Util/Common.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Util/Standards.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Util/Timing.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/src/Util/Tokens.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/AllTests.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/AllTests.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/B.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/C.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/Sub/C.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/ErrorSuppressionTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/FileList.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/TestSuite.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/TestSuite7.php create mode 100644 kirki-composer/squizlabs/php_codesniffer/tests/bootstrap.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/.gitattributes create mode 100644 kirki-composer/wp-coding-standards/wpcs/.gitignore create mode 100644 kirki-composer/wp-coding-standards/wpcs/CHANGELOG.md create mode 100644 kirki-composer/wp-coding-standards/wpcs/LICENSE create mode 100644 kirki-composer/wp-coding-standards/wpcs/README.md create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/PrecisionAlignmentSniff.php create mode 100644 kirki-composer/wp-coding-standards/wpcs/WordPress/ruleset.xml create mode 100644 kirki-composer/wp-coding-standards/wpcs/composer.json create mode 100644 kirki-composer/wp-coding-standards/wpcs/phpcs.xml.dist.sample create mode 100644 kirki-composer/wptrt/wpthemereview/CHANGELOG.md create mode 100644 kirki-composer/wptrt/wpthemereview/LICENSE.txt create mode 100644 kirki-composer/wptrt/wpthemereview/README.md create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/CoreFunctionality/FileIncludeSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/CoreFunctionality/NoDeregisterCoreScriptSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/CoreFunctionality/NoFaviconSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/CoreFunctionality/NoTitleTagSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/CoreFunctionality/PostsPerPageSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/CoreFunctionality/PrefixAllGlobalsSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/PluginTerritory/AdminBarRemovalSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/PluginTerritory/ForbiddenFunctionsSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/PluginTerritory/NoAddAdminPagesSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/PluginTerritory/SessionFunctionsUsageSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/PluginTerritory/SessionVariableUsageSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/Plugins/CorrectTGMPAVersionSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/Privacy/ShortenedURLsSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/Templates/ReservedFileNamePrefixSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/ThouShallNotUse/ForbiddenIframeSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/Sniffs/ThouShallNotUse/NoAutoGenerateSniff.php create mode 100644 kirki-composer/wptrt/wpthemereview/WPThemeReview/ruleset.xml create mode 100644 kirki-composer/wptrt/wpthemereview/composer.json rename {packages => kirki-packages}/compatibility/LICENSE (100%) rename {packages => kirki-packages}/compatibility/src/Aliases.php (100%) rename {packages => kirki-packages}/compatibility/src/Config.php (100%) rename {packages => kirki-packages}/compatibility/src/Control.php (100%) rename {packages => kirki-packages}/compatibility/src/Deprecated.php (100%) rename {packages => kirki-packages}/compatibility/src/Field.php (100%) rename {packages => kirki-packages}/compatibility/src/Framework.php (100%) rename {packages => kirki-packages}/compatibility/src/Init.php (100%) rename {packages => kirki-packages}/compatibility/src/Kirki.php (100%) rename {packages => kirki-packages}/compatibility/src/Modules.php (100%) rename {packages => kirki-packages}/compatibility/src/Sanitize_Values.php (100%) rename {packages => kirki-packages}/compatibility/src/Scripts.php (100%) rename {packages => kirki-packages}/compatibility/src/Settings.php (100%) rename {packages => kirki-packages}/compatibility/src/Values.php (100%) rename {packages => kirki-packages}/compatibility/src/deprecated/classes.php (100%) rename {packages => kirki-packages}/compatibility/src/deprecated/filters.php (100%) rename {packages => kirki-packages}/compatibility/src/deprecated/functions.php (100%) rename {packages => kirki-packages}/compatibility/src/scripts/hooks.js (100%) rename {packages => kirki-packages}/compatibility/src/scripts/i18n.js (100%) rename {packages => kirki-packages}/compatibility/src/scripts/wp-polyfill.js (100%) rename {packages => kirki-packages}/control-base/LICENSE (100%) rename {packages => kirki-packages}/control-base/dist/control.css (100%) rename {packages => kirki-packages}/control-base/dist/control.css.map (100%) rename {packages => kirki-packages}/control-base/dist/control.js (100%) rename {packages => kirki-packages}/control-base/dist/control.js.map (100%) rename {packages => kirki-packages}/control-base/src/Control/Base.php (100%) rename {packages => kirki-packages}/control-base/src/control.js (100%) rename {packages => kirki-packages}/control-base/src/control.scss (100%) rename {packages => kirki-packages}/control-base/src/dynamic-control.js (100%) rename {packages => kirki-packages}/control-base/src/rtl.scss (100%) rename {packages => kirki-packages}/control-checkbox/LICENSE (100%) rename {packages => kirki-packages}/control-checkbox/dist/control.css (100%) rename {packages => kirki-packages}/control-checkbox/dist/control.css.map (100%) rename {packages => kirki-packages}/control-checkbox/dist/control.js (100%) rename {packages => kirki-packages}/control-checkbox/dist/control.js.map (100%) rename {packages => kirki-packages}/control-checkbox/src/Control/Checkbox.php (100%) rename {packages => kirki-packages}/control-checkbox/src/Control/Checkbox_Switch.php (100%) rename {packages => kirki-packages}/control-checkbox/src/Control/Checkbox_Toggle.php (100%) rename {packages => kirki-packages}/control-checkbox/src/Field/Checkbox.php (100%) rename {packages => kirki-packages}/control-checkbox/src/Field/Checkbox_Switch.php (100%) rename {packages => kirki-packages}/control-checkbox/src/Field/Checkbox_Toggle.php (100%) rename {packages => kirki-packages}/control-checkbox/src/control.js (100%) rename {packages => kirki-packages}/control-checkbox/src/control.scss (100%) rename {packages => kirki-packages}/control-checkbox/src/scss/_vars.scss (100%) rename {packages => kirki-packages}/control-code/LICENSE (100%) rename {packages => kirki-packages}/control-code/src/Control/Code.php (100%) rename {packages => kirki-packages}/control-code/src/Field/Code.php (100%) rename {packages => kirki-packages}/control-color-palette/dist/control.css (100%) rename {packages => kirki-packages}/control-color-palette/dist/control.css.map (100%) rename {packages => kirki-packages}/control-color-palette/dist/control.js (100%) rename {packages => kirki-packages}/control-color-palette/dist/control.js.map (100%) rename {packages => kirki-packages}/control-color-palette/src/Control/Color_Palette.php (100%) rename {packages => kirki-packages}/control-color-palette/src/Field/Color_Palette.php (100%) rename {packages => kirki-packages}/control-color-palette/src/KirkiColorPaletteControl.js (100%) rename {packages => kirki-packages}/control-color-palette/src/KirkiColorPaletteForm.js (100%) rename {packages => kirki-packages}/control-color-palette/src/control.js (100%) rename {packages => kirki-packages}/control-color-palette/src/control.scss (100%) rename {packages => kirki-packages}/control-color/LICENSE (100%) rename {packages => kirki-packages}/control-color/src/Field/Color.php (100%) rename {packages => kirki-packages}/control-cropped-image/LICENSE (100%) rename {packages => kirki-packages}/control-cropped-image/src/Cropped_Image.php (100%) rename {packages => kirki-packages}/control-custom/LICENSE (100%) rename {packages => kirki-packages}/control-custom/src/Control/Custom.php (100%) rename {packages => kirki-packages}/control-custom/src/Field/Custom.php (100%) rename {packages => kirki-packages}/control-dashicons/LICENSE (100%) rename {packages => kirki-packages}/control-dashicons/dist/control.css (100%) rename {packages => kirki-packages}/control-dashicons/dist/control.css.map (100%) rename {packages => kirki-packages}/control-dashicons/dist/control.js (100%) rename {packages => kirki-packages}/control-dashicons/dist/control.js.map (100%) rename {packages => kirki-packages}/control-dashicons/src/Control/Dashicons.php (100%) rename {packages => kirki-packages}/control-dashicons/src/Field/Dashicons.php (100%) rename {packages => kirki-packages}/control-dashicons/src/Util/Dashicons.php (100%) rename {packages => kirki-packages}/control-dashicons/src/control.js (100%) rename {packages => kirki-packages}/control-dashicons/src/control.scss (100%) rename {packages => kirki-packages}/control-date/LICENSE (100%) rename {packages => kirki-packages}/control-date/dist/control.css (100%) rename {packages => kirki-packages}/control-date/dist/control.css.map (100%) rename {packages => kirki-packages}/control-date/dist/control.js (100%) rename {packages => kirki-packages}/control-date/dist/control.js.map (100%) rename {packages => kirki-packages}/control-date/src/Control/Date.php (100%) rename {packages => kirki-packages}/control-date/src/Field/Date.php (100%) rename {packages => kirki-packages}/control-date/src/control.js (100%) rename {packages => kirki-packages}/control-date/src/control.scss (100%) rename {packages => kirki-packages}/control-dimension/LICENSE (100%) rename {packages => kirki-packages}/control-dimension/dist/control.css (100%) rename {packages => kirki-packages}/control-dimension/dist/control.css.map (100%) rename {packages => kirki-packages}/control-dimension/dist/control.js (100%) rename {packages => kirki-packages}/control-dimension/dist/control.js.map (100%) rename {packages => kirki-packages}/control-dimension/src/Control/Dimension.php (100%) rename {packages => kirki-packages}/control-dimension/src/Field/Dimension.php (100%) rename {packages => kirki-packages}/control-dimension/src/control.js (100%) rename {packages => kirki-packages}/control-dimension/src/control.scss (100%) rename {packages => kirki-packages}/control-editor/LICENSE (100%) rename {packages => kirki-packages}/control-editor/dist/control.css (100%) rename {packages => kirki-packages}/control-editor/dist/control.css.map (100%) rename {packages => kirki-packages}/control-editor/dist/control.js (100%) rename {packages => kirki-packages}/control-editor/dist/control.js.map (100%) rename {packages => kirki-packages}/control-editor/src/Control/Editor.php (100%) rename {packages => kirki-packages}/control-editor/src/Field/Editor.php (100%) rename {packages => kirki-packages}/control-editor/src/control.js (100%) rename {packages => kirki-packages}/control-editor/src/control.scss (100%) rename {packages => kirki-packages}/control-generic/LICENSE (100%) rename {packages => kirki-packages}/control-generic/dist/control.js (100%) rename {packages => kirki-packages}/control-generic/dist/control.js.map (100%) rename {packages => kirki-packages}/control-generic/src/Control/Generic.php (100%) rename {packages => kirki-packages}/control-generic/src/Field/Generic.php (100%) rename {packages => kirki-packages}/control-generic/src/Field/Number.php (100%) rename {packages => kirki-packages}/control-generic/src/Field/Text.php (100%) rename {packages => kirki-packages}/control-generic/src/Field/Textarea.php (100%) rename {packages => kirki-packages}/control-generic/src/Field/URL.php (100%) rename {packages => kirki-packages}/control-generic/src/control.js (100%) rename {packages => kirki-packages}/control-generic/src/control.scss (100%) rename {packages => kirki-packages}/control-image/LICENSE (100%) rename {packages => kirki-packages}/control-image/dist/control.js (100%) rename {packages => kirki-packages}/control-image/dist/control.js.map (100%) rename {packages => kirki-packages}/control-image/src/Control/Image.php (100%) rename {packages => kirki-packages}/control-image/src/Field/CSS/Image.php (100%) rename {packages => kirki-packages}/control-image/src/Field/Image.php (100%) rename {packages => kirki-packages}/control-image/src/control.js (100%) rename {packages => kirki-packages}/control-multicheck/LICENSE (100%) rename {packages => kirki-packages}/control-multicheck/dist/control.css (100%) rename {packages => kirki-packages}/control-multicheck/dist/control.css.map (100%) rename {packages => kirki-packages}/control-multicheck/dist/control.js (100%) rename {packages => kirki-packages}/control-multicheck/dist/control.js.map (100%) rename {packages => kirki-packages}/control-multicheck/src/Control/Multicheck.php (100%) rename {packages => kirki-packages}/control-multicheck/src/Field/Multicheck.php (100%) rename {packages => kirki-packages}/control-multicheck/src/control.js (100%) rename {packages => kirki-packages}/control-multicheck/src/control.scss (100%) rename {packages => kirki-packages}/control-palette/LICENSE (100%) rename {packages => kirki-packages}/control-palette/dist/control.css (100%) rename {packages => kirki-packages}/control-palette/dist/control.css.map (100%) rename {packages => kirki-packages}/control-palette/dist/control.js (100%) rename {packages => kirki-packages}/control-palette/dist/control.js.map (100%) rename {packages => kirki-packages}/control-palette/src/Control/Palette.php (100%) rename {packages => kirki-packages}/control-palette/src/Field/Palette.php (100%) rename {packages => kirki-packages}/control-palette/src/control.js (100%) rename {packages => kirki-packages}/control-palette/src/control.scss (100%) rename {packages => kirki-packages}/control-radio/LICENSE (100%) rename {packages => kirki-packages}/control-radio/dist/control.css (100%) rename {packages => kirki-packages}/control-radio/dist/control.css.map (100%) rename {packages => kirki-packages}/control-radio/dist/control.js (100%) rename {packages => kirki-packages}/control-radio/dist/control.js.map (100%) rename {packages => kirki-packages}/control-radio/src/Control/Radio.php (100%) rename {packages => kirki-packages}/control-radio/src/Control/Radio_Buttonset.php (100%) rename {packages => kirki-packages}/control-radio/src/Control/Radio_Image.php (100%) rename {packages => kirki-packages}/control-radio/src/Field/Radio.php (100%) rename {packages => kirki-packages}/control-radio/src/Field/Radio_Buttonset.php (100%) rename {packages => kirki-packages}/control-radio/src/Field/Radio_Image.php (100%) rename {packages => kirki-packages}/control-radio/src/control.js (100%) rename {packages => kirki-packages}/control-radio/src/control.scss (100%) rename {packages => kirki-packages}/control-radio/src/scss/_radio-buttonset.scss (100%) rename {packages => kirki-packages}/control-radio/src/scss/_radio-image.scss (100%) rename {packages => kirki-packages}/control-radio/src/scss/_radio.scss (100%) rename {packages => kirki-packages}/control-react-colorful/LICENSE (100%) rename {packages => kirki-packages}/control-react-colorful/dist/control.css (100%) rename {packages => kirki-packages}/control-react-colorful/dist/control.css.map (100%) rename {packages => kirki-packages}/control-react-colorful/dist/control.js (100%) rename {packages => kirki-packages}/control-react-colorful/dist/control.js.map (100%) rename {packages => kirki-packages}/control-react-colorful/dist/preview.js (100%) rename {packages => kirki-packages}/control-react-colorful/dist/preview.js.map (100%) rename {packages => kirki-packages}/control-react-colorful/src/Control/ReactColorful.php (100%) rename {packages => kirki-packages}/control-react-colorful/src/Field/CSS/ReactColorful.php (100%) rename {packages => kirki-packages}/control-react-colorful/src/Field/ReactColorful.php (100%) rename {packages => kirki-packages}/control-react-colorful/src/KirkiReactColorfulControl.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/KirkiReactColorfulForm.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/control.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/control.scss (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/components/KirkiReactColorfulCircle.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/components/KirkiReactColorfulInput.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/components/KirkiReactColorfulSwatches.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/hooks/useClickOutside.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/hooks/useFocusOutside.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/hooks/useWindowResize.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/utils/convertColorForCustomizer.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/utils/convertColorForInput.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/utils/convertColorForPicker.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/js/utils/util.js (100%) rename {packages => kirki-packages}/control-react-colorful/src/preview.js (100%) rename {packages => kirki-packages}/control-react-select/LICENSE (100%) rename {packages => kirki-packages}/control-react-select/dist/control.css (100%) rename {packages => kirki-packages}/control-react-select/dist/control.css.map (100%) rename {packages => kirki-packages}/control-react-select/dist/control.js (100%) rename {packages => kirki-packages}/control-react-select/dist/control.js.LICENSE.txt (100%) rename {packages => kirki-packages}/control-react-select/dist/control.js.map (100%) rename {packages => kirki-packages}/control-react-select/src/Control/ReactSelect.php (100%) rename {packages => kirki-packages}/control-react-select/src/Field/ReactSelect.php (100%) rename {packages => kirki-packages}/control-react-select/src/KirkiSelectControl.js (100%) rename {packages => kirki-packages}/control-react-select/src/KirkiSelectForm.js (100%) rename {packages => kirki-packages}/control-react-select/src/control.js (100%) rename {packages => kirki-packages}/control-react-select/src/control.scss (100%) rename {packages => kirki-packages}/control-repeater/LICENSE (100%) rename {packages => kirki-packages}/control-repeater/dist/control.css (100%) rename {packages => kirki-packages}/control-repeater/dist/control.css.map (100%) rename {packages => kirki-packages}/control-repeater/dist/control.js (100%) rename {packages => kirki-packages}/control-repeater/dist/control.js.map (100%) rename {packages => kirki-packages}/control-repeater/dist/wp-color-picker-alpha.min.js (100%) rename {packages => kirki-packages}/control-repeater/src/Control/Repeater.php (100%) rename {packages => kirki-packages}/control-repeater/src/Field/Repeater.php (100%) rename {packages => kirki-packages}/control-repeater/src/Settings/Repeater.php (100%) rename {packages => kirki-packages}/control-repeater/src/control.js (100%) rename {packages => kirki-packages}/control-repeater/src/control.scss (100%) rename {packages => kirki-packages}/control-select/src/Field/Dropdown_Pages.php (100%) rename {packages => kirki-packages}/control-select/src/Field/Preset.php (100%) rename {packages => kirki-packages}/control-select/src/Field/Select.php (100%) rename {packages => kirki-packages}/control-slider/dist/control.css (100%) rename {packages => kirki-packages}/control-slider/dist/control.css.map (100%) rename {packages => kirki-packages}/control-slider/dist/control.js (100%) rename {packages => kirki-packages}/control-slider/dist/control.js.map (100%) rename {packages => kirki-packages}/control-slider/src/Control/Slider.php (100%) rename {packages => kirki-packages}/control-slider/src/Field/Slider.php (100%) rename {packages => kirki-packages}/control-slider/src/KirkiSliderControl.js (100%) rename {packages => kirki-packages}/control-slider/src/KirkiSliderForm.js (100%) rename {packages => kirki-packages}/control-slider/src/control.js (100%) rename {packages => kirki-packages}/control-slider/src/control.scss (100%) rename {packages => kirki-packages}/control-sortable/LICENSE (100%) rename {packages => kirki-packages}/control-sortable/dist/control.css (100%) rename {packages => kirki-packages}/control-sortable/dist/control.css.map (100%) rename {packages => kirki-packages}/control-sortable/dist/control.js (100%) rename {packages => kirki-packages}/control-sortable/dist/control.js.map (100%) rename {packages => kirki-packages}/control-sortable/src/Control/Sortable.php (100%) rename {packages => kirki-packages}/control-sortable/src/Field/Sortable.php (100%) rename {packages => kirki-packages}/control-sortable/src/control.js (100%) rename {packages => kirki-packages}/control-sortable/src/control.scss (100%) rename {packages => kirki-packages}/control-upload/LICENSE (100%) rename {packages => kirki-packages}/control-upload/src/Control/Upload.php (100%) rename {packages => kirki-packages}/control-upload/src/Field/Upload.php (100%) rename {packages => kirki-packages}/data-option/LICENSE (100%) rename {packages => kirki-packages}/data-option/src/Option.php (100%) rename {packages => kirki-packages}/field-background/LICENSE (100%) rename {packages => kirki-packages}/field-background/src/Background.php (100%) rename {packages => kirki-packages}/field-background/src/CSS/Background.php (100%) rename {packages => kirki-packages}/field-background/src/script.js (100%) rename {packages => kirki-packages}/field-dimensions/LICENSE (100%) rename {packages => kirki-packages}/field-dimensions/dist/control.css (100%) rename {packages => kirki-packages}/field-dimensions/dist/control.css.map (100%) rename {packages => kirki-packages}/field-dimensions/dist/preview.js (100%) rename {packages => kirki-packages}/field-dimensions/dist/preview.js.map (100%) rename {packages => kirki-packages}/field-dimensions/src/CSS/Dimensions.php (100%) rename {packages => kirki-packages}/field-dimensions/src/Dimensions.php (100%) rename {packages => kirki-packages}/field-dimensions/src/control.scss (100%) rename {packages => kirki-packages}/field-dimensions/src/preview.js (100%) rename {packages => kirki-packages}/field-fontawesome/LICENSE (100%) rename {packages => kirki-packages}/field-fontawesome/src/Field/FontAwesome.php (100%) rename {packages => kirki-packages}/field-fontawesome/src/Field/fontawesome.json (100%) rename {packages => kirki-packages}/field-multicolor/LICENSE (100%) rename {packages => kirki-packages}/field-multicolor/src/Field/CSS/Multicolor.php (100%) rename {packages => kirki-packages}/field-multicolor/src/Field/Multicolor.php (100%) rename {packages => kirki-packages}/field-typography/LICENSE (100%) rename {packages => kirki-packages}/field-typography/dist/control.css (100%) rename {packages => kirki-packages}/field-typography/dist/control.css.map (100%) rename {packages => kirki-packages}/field-typography/dist/control.js (100%) rename {packages => kirki-packages}/field-typography/dist/control.js.map (100%) rename {packages => kirki-packages}/field-typography/dist/preview.js (100%) rename {packages => kirki-packages}/field-typography/dist/preview.js.map (100%) rename {packages => kirki-packages}/field-typography/src/Field/CSS/Typography.php (100%) rename {packages => kirki-packages}/field-typography/src/Field/Typography.php (100%) rename {packages => kirki-packages}/field-typography/src/control.js (100%) rename {packages => kirki-packages}/field-typography/src/control.scss (100%) rename {packages => kirki-packages}/field-typography/src/preview.js (100%) rename {packages => kirki-packages}/field/LICENSE (100%) rename {packages => kirki-packages}/field/src/Field.php (98%) rename {packages => kirki-packages}/field/src/Field/None.php (100%) rename {packages => kirki-packages}/googlefonts/Gruntfile.js (100%) rename {packages => kirki-packages}/googlefonts/LICENSE (100%) rename {packages => kirki-packages}/googlefonts/src/GoogleFonts.php (100%) rename {packages => kirki-packages}/googlefonts/src/webfont-files.json (100%) rename {packages => kirki-packages}/googlefonts/src/webfont-names.json (100%) rename {packages => kirki-packages}/googlefonts/src/webfonts.json (100%) rename {packages => kirki-packages}/l10n/LICENSE (100%) rename {packages => kirki-packages}/l10n/src/L10n.php (100%) rename {packages => kirki-packages}/module-css/LICENSE (100%) rename {packages => kirki-packages}/module-css/src/CSS.php (100%) rename {packages => kirki-packages}/module-css/src/CSS/Generator.php (100%) rename {packages => kirki-packages}/module-css/src/CSS/Output.php (100%) rename {packages => kirki-packages}/module-css/src/CSS/Property.php (100%) rename {packages => kirki-packages}/module-css/src/CSS/Property/Background_Image.php (100%) rename {packages => kirki-packages}/module-css/src/CSS/Property/Background_Position.php (100%) rename {packages => kirki-packages}/module-css/src/CSS/Property/Font_Family.php (100%) rename {packages => kirki-packages}/module-editor-styles/LICENSE (100%) rename {packages => kirki-packages}/module-editor-styles/src/Editor_Styles.php (100%) rename {packages => kirki-packages}/module-field-dependencies/LICENSE (100%) rename {packages => kirki-packages}/module-field-dependencies/dist/control.js (100%) rename {packages => kirki-packages}/module-field-dependencies/dist/control.js.map (100%) rename {packages => kirki-packages}/module-field-dependencies/src/Field_Dependencies.php (100%) rename {packages => kirki-packages}/module-field-dependencies/src/control.js (100%) rename {packages => kirki-packages}/module-panels/LICENSE (100%) rename {packages => kirki-packages}/module-panels/src/Panel.php (100%) rename {packages => kirki-packages}/module-panels/src/Panel_Types/Nested.php (100%) rename {packages => kirki-packages}/module-panels/src/script.js (100%) rename {packages => kirki-packages}/module-postmessage/LICENSE (100%) rename {packages => kirki-packages}/module-postmessage/src/Postmessage.php (100%) rename {packages => kirki-packages}/module-postmessage/src/postMessage.js (100%) rename {packages => kirki-packages}/module-preset/LICENSE (100%) rename {packages => kirki-packages}/module-preset/src/Preset.php (100%) rename {packages => kirki-packages}/module-preset/src/script.js (100%) rename {packages => kirki-packages}/module-section-icons/LICENSE (100%) rename {packages => kirki-packages}/module-section-icons/src/Section_Icons.php (100%) rename {packages => kirki-packages}/module-section-icons/src/icons.js (100%) rename {packages => kirki-packages}/module-sections/LICENSE (100%) rename {packages => kirki-packages}/module-sections/src/Section.php (100%) rename {packages => kirki-packages}/module-sections/src/Section_Types/Expanded.php (100%) rename {packages => kirki-packages}/module-sections/src/Section_Types/Link.php (100%) rename {packages => kirki-packages}/module-sections/src/Section_Types/Nested.php (100%) rename {packages => kirki-packages}/module-sections/src/Section_Types/Outer.php (100%) rename {packages => kirki-packages}/module-sections/src/script.js (100%) rename {packages => kirki-packages}/module-sections/src/styles.css (100%) rename {packages => kirki-packages}/module-selective-refresh/LICENSE (100%) rename {packages => kirki-packages}/module-selective-refresh/src/Selective_Refresh.php (100%) rename {packages => kirki-packages}/module-tooltips/LICENSE (100%) rename {packages => kirki-packages}/module-tooltips/dist/control.css (100%) rename {packages => kirki-packages}/module-tooltips/dist/control.css.map (100%) rename {packages => kirki-packages}/module-tooltips/dist/control.js (100%) rename {packages => kirki-packages}/module-tooltips/dist/control.js.map (100%) rename {packages => kirki-packages}/module-tooltips/src/Tooltips.php (100%) rename {packages => kirki-packages}/module-tooltips/src/control.js (100%) rename {packages => kirki-packages}/module-tooltips/src/control.scss (100%) rename {packages => kirki-packages}/module-webfonts/LICENSE (100%) rename {packages => kirki-packages}/module-webfonts/src/Webfonts.php (100%) rename {packages => kirki-packages}/module-webfonts/src/Webfonts/Async.php (100%) rename {packages => kirki-packages}/module-webfonts/src/Webfonts/Downloader.php (100%) rename {packages => kirki-packages}/module-webfonts/src/Webfonts/Embed.php (100%) rename {packages => kirki-packages}/module-webfonts/src/Webfonts/Fonts.php (100%) rename {packages => kirki-packages}/module-webfonts/src/Webfonts/Google.php (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/closure.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/cssclassname.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/domhelper.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/eventdispatcher.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/font.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/fontmodule.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/fontmoduleloader.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/fontruler.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/fontwatcher.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/fontwatchrunner.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/initialize.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/nativefontwatchrunner.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/stylesheetwaiter.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/core/webfont.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules.yml (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/custom.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/fontdeck.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/google/fontapiparser.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/google/fontapiurlbuilder.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/google/googlefontapi.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/monotype.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/src/modules/typekit.js (100%) rename {packages => kirki-packages}/module-webfonts/src/assets/scripts/vendor-typekit/webfontloader.js (100%) rename {packages => kirki-packages}/settings/dist/admin-notice.css (100%) create mode 100644 kirki-packages/settings/dist/admin-notice.css.map rename {packages => kirki-packages}/settings/dist/discount-notice.js (100%) create mode 100644 kirki-packages/settings/dist/discount-notice.js.map rename {packages => kirki-packages}/settings/dist/heatbox.css (100%) rename {packages => kirki-packages}/settings/dist/settings.css (100%) create mode 100644 kirki-packages/settings/dist/settings.css.map rename {packages => kirki-packages}/settings/dist/settings.js (100%) create mode 100644 kirki-packages/settings/dist/settings.js.map rename {packages => kirki-packages}/settings/src/Notice.php (93%) rename {packages => kirki-packages}/settings/src/SetupSettings.php (91%) rename {packages => kirki-packages}/settings/src/admin-notice.scss (100%) rename {packages => kirki-packages}/settings/src/discount-notice.ts (100%) rename {packages => kirki-packages}/settings/src/settings.scss (100%) rename {packages => kirki-packages}/settings/src/settings.ts (100%) rename {packages => kirki-packages}/settings/src/setup-udb.ts (100%) rename {packages => kirki-packages}/settings/src/tabs.ts (100%) rename {packages => kirki-packages}/settings/src/utils.ts (100%) rename {packages => kirki-packages}/settings/templates/metaboxes/clear-font-cache.php (100%) rename {packages => kirki-packages}/settings/templates/metaboxes/documentation.php (100%) rename {packages => kirki-packages}/settings/templates/metaboxes/installation-progress.php (100%) rename {packages => kirki-packages}/settings/templates/metaboxes/recommended-plugins.php (100%) rename {packages => kirki-packages}/settings/templates/metaboxes/ultimate-dashboard.php (100%) rename {packages => kirki-packages}/settings/templates/settings-template.php (100%) rename {packages => kirki-packages}/url-getter/LICENSE (100%) rename {packages => kirki-packages}/url-getter/src/URL.php (100%) rename {packages => kirki-packages}/util/LICENSE (100%) rename {packages => kirki-packages}/util/src/Helper.php (100%) rename {packages => kirki-packages}/util/src/MaterialColors.php (100%) rename {packages => kirki-packages}/util/src/Setting/Site_Option.php (100%) rename {packages => kirki-packages}/util/src/Setting/User_Meta.php (100%) rename {packages => kirki-packages}/util/src/Util.php (100%) delete mode 100644 packages/settings/dist/admin-notice.css.map delete mode 100644 packages/settings/dist/discount-notice.js.map delete mode 100644 packages/settings/dist/settings.css.map delete mode 100644 packages/settings/dist/settings.js.map delete mode 100644 vendor/composer/autoload_psr4.php delete mode 100644 vendor/composer/autoload_static.php diff --git a/.gitattributes b/.gitattributes index b5c0bc93d..b9e48cefb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -24,10 +24,10 @@ composer.json export-ignore composer.lock export-ignore Gruntfile.js export-ignore package.json export-ignore -packages/**/installed.json export-ignore -packages/kirki-framework/**/.gitignore export-ignore -packages/kirki-framework/**/package.json export-ignore -packages/kirki-framework/**/Gruntfile.js export-ignore +kirki-composer/**/installed.json export-ignore +kirki-packages/**/.gitignore export-ignore +kirki-packages/**/package.json export-ignore +kirki-packages/**/Gruntfile.js export-ignore *.map export-ignore .sass-cache export-ignore *.scss export-ignore diff --git a/build.sh b/build.sh index 077da5e8b..8171d98cb 100644 --- a/build.sh +++ b/build.sh @@ -46,8 +46,8 @@ echo "Removing un-necessary files inside individual packages ..." # Would you like to remove the CSS source files? # If so, un-comment the following lines. -# rm -rf packages/**/src/*.scss -# rm -rf packages/**/src/scss/*.scss +# rm -rf kirki-packages/**/src/*.scss +# rm -rf kirki-packages/**/src/scss/*.scss cd ../../ diff --git a/composer.json b/composer.json index 3a12e5bca..9b94b7458 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "config": { - "vendor-dir": "vendor", + "vendor-dir": "kirki-composer", "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, "composer/installers": true @@ -29,68 +29,68 @@ "autoload": { "psr-4": { "Kirki\\Compatibility\\": [ - "packages/compatibility/src" + "kirki-packages/compatibility/src" ], "Kirki\\Data\\": [ - "packages/data-option/src" + "kirki-packages/data-option/src" ], "Kirki\\Field\\": [ - "packages/field/src/Field", - "packages/field-background/src", - "packages/field-dimensions/src", - "packages/field-fontawesome/src", - "packages/field-multicolor/src/Field", - "packages/field-multicolor/src", - "packages/field-typography/src/Field", - "packages/field-typography/src" + "kirki-packages/field/src/Field", + "kirki-packages/field-background/src", + "kirki-packages/field-dimensions/src", + "kirki-packages/field-fontawesome/src", + "kirki-packages/field-multicolor/src/Field", + "kirki-packages/field-multicolor/src", + "kirki-packages/field-typography/src/Field", + "kirki-packages/field-typography/src" ], "Kirki\\Module\\": [ - "packages/module-css/src", - "packages/module-editor-styles/src", - "packages/module-field-dependencies/src", - "packages/module-postmessage/src", - "packages/module-preset/src", - "packages/module-section-icons/src", - "packages/module-selective-refresh/src", - "packages/module-tooltips/src", - "packages/module-webfonts/src" + "kirki-packages/module-css/src", + "kirki-packages/module-editor-styles/src", + "kirki-packages/module-field-dependencies/src", + "kirki-packages/module-postmessage/src", + "kirki-packages/module-preset/src", + "kirki-packages/module-section-icons/src", + "kirki-packages/module-selective-refresh/src", + "kirki-packages/module-tooltips/src", + "kirki-packages/module-webfonts/src" ], "Kirki\\Util\\": [ - "packages/util/src" + "kirki-packages/util/src" ], "Kirki\\Settings\\": [ - "packages/settings/src" + "kirki-packages/settings/src" ], "Kirki\\": [ - "packages/control-base/src", - "packages/control-checkbox/src", - "packages/control-code/src", - "packages/control-color/src", - "packages/control-color-palette/src", - "packages/control-cropped-image/src", - "packages/control-custom/src", - "packages/control-dashicons/src", - "packages/control-date/src", - "packages/control-dimension/src", - "packages/control-editor/src", - "packages/control-generic/src", - "packages/control-image/src", - "packages/control-multicheck/src", - "packages/control-palette/src", - "packages/control-radio/src", - "packages/control-react-colorful/src", - "packages/control-react-select/src", - "packages/control-repeater/src", - "packages/control-select/src", - "packages/control-slider/src", - "packages/control-sortable/src", - "packages/control-upload/src", - "packages/field/src", - "packages/googlefonts/src", - "packages/l10n/src", - "packages/module-panels/src", - "packages/module-sections/src", - "packages/url-getter/src" + "kirki-packages/control-base/src", + "kirki-packages/control-checkbox/src", + "kirki-packages/control-code/src", + "kirki-packages/control-color/src", + "kirki-packages/control-color-palette/src", + "kirki-packages/control-cropped-image/src", + "kirki-packages/control-custom/src", + "kirki-packages/control-dashicons/src", + "kirki-packages/control-date/src", + "kirki-packages/control-dimension/src", + "kirki-packages/control-editor/src", + "kirki-packages/control-generic/src", + "kirki-packages/control-image/src", + "kirki-packages/control-multicheck/src", + "kirki-packages/control-palette/src", + "kirki-packages/control-radio/src", + "kirki-packages/control-react-colorful/src", + "kirki-packages/control-react-select/src", + "kirki-packages/control-repeater/src", + "kirki-packages/control-select/src", + "kirki-packages/control-slider/src", + "kirki-packages/control-sortable/src", + "kirki-packages/control-upload/src", + "kirki-packages/field/src", + "kirki-packages/googlefonts/src", + "kirki-packages/l10n/src", + "kirki-packages/module-panels/src", + "kirki-packages/module-sections/src", + "kirki-packages/url-getter/src" ] } }, diff --git a/vendor/autoload.php b/kirki-composer/autoload.php similarity index 91% rename from vendor/autoload.php rename to kirki-composer/autoload.php index 2d4228a2a..a6b068ba5 100644 --- a/vendor/autoload.php +++ b/kirki-composer/autoload.php @@ -22,4 +22,4 @@ require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInitc56aa391ac498061f8d648878e0e6144::getLoader(); +return ComposerAutoloaderInit734b74506bf23405b8270b65bdba2dd6::getLoader(); diff --git a/kirki-composer/bin/phpcbf b/kirki-composer/bin/phpcbf new file mode 100644 index 000000000..0b622008f --- /dev/null +++ b/kirki-composer/bin/phpcbf @@ -0,0 +1,120 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + include("phpvfscomposer://" . __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcbf'); + exit(0); + } +} + +include __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcbf'; diff --git a/kirki-composer/bin/phpcbf.bat b/kirki-composer/bin/phpcbf.bat new file mode 100644 index 000000000..f48942856 --- /dev/null +++ b/kirki-composer/bin/phpcbf.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpcbf +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/kirki-composer/bin/phpcs b/kirki-composer/bin/phpcs new file mode 100644 index 000000000..9eb8455a8 --- /dev/null +++ b/kirki-composer/bin/phpcs @@ -0,0 +1,120 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + include("phpvfscomposer://" . __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcs'); + exit(0); + } +} + +include __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcs'; diff --git a/kirki-composer/bin/phpcs.bat b/kirki-composer/bin/phpcs.bat new file mode 100644 index 000000000..ea984e988 --- /dev/null +++ b/kirki-composer/bin/phpcs.bat @@ -0,0 +1,5 @@ +@ECHO OFF +setlocal DISABLEDELAYEDEXPANSION +SET BIN_TARGET=%~dp0/phpcs +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 +php "%BIN_TARGET%" %* diff --git a/vendor/composer/ClassLoader.php b/kirki-composer/composer/ClassLoader.php similarity index 100% rename from vendor/composer/ClassLoader.php rename to kirki-composer/composer/ClassLoader.php diff --git a/vendor/composer/InstalledVersions.php b/kirki-composer/composer/InstalledVersions.php similarity index 100% rename from vendor/composer/InstalledVersions.php rename to kirki-composer/composer/InstalledVersions.php diff --git a/vendor/composer/LICENSE b/kirki-composer/composer/LICENSE similarity index 100% rename from vendor/composer/LICENSE rename to kirki-composer/composer/LICENSE diff --git a/vendor/composer/autoload_classmap.php b/kirki-composer/composer/autoload_classmap.php similarity index 100% rename from vendor/composer/autoload_classmap.php rename to kirki-composer/composer/autoload_classmap.php diff --git a/vendor/composer/autoload_namespaces.php b/kirki-composer/composer/autoload_namespaces.php similarity index 100% rename from vendor/composer/autoload_namespaces.php rename to kirki-composer/composer/autoload_namespaces.php diff --git a/kirki-composer/composer/autoload_psr4.php b/kirki-composer/composer/autoload_psr4.php new file mode 100644 index 000000000..3f6932504 --- /dev/null +++ b/kirki-composer/composer/autoload_psr4.php @@ -0,0 +1,18 @@ + array($vendorDir . '/dealerdirect/phpcodesniffer-composer-installer/src'), + 'Kirki\\Util\\' => array($baseDir . '/kirki-packages/util/src'), + 'Kirki\\Settings\\' => array($baseDir . '/kirki-packages/settings/src'), + 'Kirki\\Module\\' => array($baseDir . '/kirki-packages/module-css/src', $baseDir . '/kirki-packages/module-editor-styles/src', $baseDir . '/kirki-packages/module-field-dependencies/src', $baseDir . '/kirki-packages/module-postmessage/src', $baseDir . '/kirki-packages/module-preset/src', $baseDir . '/kirki-packages/module-section-icons/src', $baseDir . '/kirki-packages/module-selective-refresh/src', $baseDir . '/kirki-packages/module-tooltips/src', $baseDir . '/kirki-packages/module-webfonts/src'), + 'Kirki\\Field\\' => array($baseDir . '/kirki-packages/field/src/Field', $baseDir . '/kirki-packages/field-background/src', $baseDir . '/kirki-packages/field-dimensions/src', $baseDir . '/kirki-packages/field-fontawesome/src', $baseDir . '/kirki-packages/field-multicolor/src/Field', $baseDir . '/kirki-packages/field-multicolor/src', $baseDir . '/kirki-packages/field-typography/src/Field', $baseDir . '/kirki-packages/field-typography/src'), + 'Kirki\\Data\\' => array($baseDir . '/kirki-packages/data-option/src'), + 'Kirki\\Compatibility\\' => array($baseDir . '/kirki-packages/compatibility/src'), + 'Kirki\\' => array($baseDir . '/kirki-packages/control-base/src', $baseDir . '/kirki-packages/control-checkbox/src', $baseDir . '/kirki-packages/control-code/src', $baseDir . '/kirki-packages/control-color/src', $baseDir . '/kirki-packages/control-color-palette/src', $baseDir . '/kirki-packages/control-cropped-image/src', $baseDir . '/kirki-packages/control-custom/src', $baseDir . '/kirki-packages/control-dashicons/src', $baseDir . '/kirki-packages/control-date/src', $baseDir . '/kirki-packages/control-dimension/src', $baseDir . '/kirki-packages/control-editor/src', $baseDir . '/kirki-packages/control-generic/src', $baseDir . '/kirki-packages/control-image/src', $baseDir . '/kirki-packages/control-multicheck/src', $baseDir . '/kirki-packages/control-palette/src', $baseDir . '/kirki-packages/control-radio/src', $baseDir . '/kirki-packages/control-react-colorful/src', $baseDir . '/kirki-packages/control-react-select/src', $baseDir . '/kirki-packages/control-repeater/src', $baseDir . '/kirki-packages/control-select/src', $baseDir . '/kirki-packages/control-slider/src', $baseDir . '/kirki-packages/control-sortable/src', $baseDir . '/kirki-packages/control-upload/src', $baseDir . '/kirki-packages/field/src', $baseDir . '/kirki-packages/googlefonts/src', $baseDir . '/kirki-packages/l10n/src', $baseDir . '/kirki-packages/module-panels/src', $baseDir . '/kirki-packages/module-sections/src', $baseDir . '/kirki-packages/url-getter/src'), + 'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'), +); diff --git a/vendor/composer/autoload_real.php b/kirki-composer/composer/autoload_real.php similarity index 67% rename from vendor/composer/autoload_real.php rename to kirki-composer/composer/autoload_real.php index 400add26c..242734e62 100644 --- a/vendor/composer/autoload_real.php +++ b/kirki-composer/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitc56aa391ac498061f8d648878e0e6144 +class ComposerAutoloaderInit734b74506bf23405b8270b65bdba2dd6 { private static $loader; @@ -24,16 +24,16 @@ public static function getLoader() require __DIR__ . '/platform_check.php'; - spl_autoload_register(array('ComposerAutoloaderInitc56aa391ac498061f8d648878e0e6144', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit734b74506bf23405b8270b65bdba2dd6', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInitc56aa391ac498061f8d648878e0e6144', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit734b74506bf23405b8270b65bdba2dd6', 'loadClassLoader')); $includePaths = require __DIR__ . '/include_paths.php'; $includePaths[] = get_include_path(); set_include_path(implode(PATH_SEPARATOR, $includePaths)); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInitc56aa391ac498061f8d648878e0e6144::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit734b74506bf23405b8270b65bdba2dd6::getInitializer($loader)); $loader->register(true); diff --git a/kirki-composer/composer/autoload_static.php b/kirki-composer/composer/autoload_static.php new file mode 100644 index 000000000..9edae6f34 --- /dev/null +++ b/kirki-composer/composer/autoload_static.php @@ -0,0 +1,125 @@ + + array ( + 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 57, + ), + 'K' => + array ( + 'Kirki\\Util\\' => 11, + 'Kirki\\Settings\\' => 15, + 'Kirki\\Module\\' => 13, + 'Kirki\\Field\\' => 12, + 'Kirki\\Data\\' => 11, + 'Kirki\\Compatibility\\' => 20, + 'Kirki\\' => 6, + ), + 'C' => + array ( + 'Composer\\Installers\\' => 20, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => + array ( + 0 => __DIR__ . '/..' . '/dealerdirect/phpcodesniffer-composer-installer/src', + ), + 'Kirki\\Util\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/util/src', + ), + 'Kirki\\Settings\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/settings/src', + ), + 'Kirki\\Module\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/module-css/src', + 1 => __DIR__ . '/../..' . '/kirki-packages/module-editor-styles/src', + 2 => __DIR__ . '/../..' . '/kirki-packages/module-field-dependencies/src', + 3 => __DIR__ . '/../..' . '/kirki-packages/module-postmessage/src', + 4 => __DIR__ . '/../..' . '/kirki-packages/module-preset/src', + 5 => __DIR__ . '/../..' . '/kirki-packages/module-section-icons/src', + 6 => __DIR__ . '/../..' . '/kirki-packages/module-selective-refresh/src', + 7 => __DIR__ . '/../..' . '/kirki-packages/module-tooltips/src', + 8 => __DIR__ . '/../..' . '/kirki-packages/module-webfonts/src', + ), + 'Kirki\\Field\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/field/src/Field', + 1 => __DIR__ . '/../..' . '/kirki-packages/field-background/src', + 2 => __DIR__ . '/../..' . '/kirki-packages/field-dimensions/src', + 3 => __DIR__ . '/../..' . '/kirki-packages/field-fontawesome/src', + 4 => __DIR__ . '/../..' . '/kirki-packages/field-multicolor/src/Field', + 5 => __DIR__ . '/../..' . '/kirki-packages/field-multicolor/src', + 6 => __DIR__ . '/../..' . '/kirki-packages/field-typography/src/Field', + 7 => __DIR__ . '/../..' . '/kirki-packages/field-typography/src', + ), + 'Kirki\\Data\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/data-option/src', + ), + 'Kirki\\Compatibility\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/compatibility/src', + ), + 'Kirki\\' => + array ( + 0 => __DIR__ . '/../..' . '/kirki-packages/control-base/src', + 1 => __DIR__ . '/../..' . '/kirki-packages/control-checkbox/src', + 2 => __DIR__ . '/../..' . '/kirki-packages/control-code/src', + 3 => __DIR__ . '/../..' . '/kirki-packages/control-color/src', + 4 => __DIR__ . '/../..' . '/kirki-packages/control-color-palette/src', + 5 => __DIR__ . '/../..' . '/kirki-packages/control-cropped-image/src', + 6 => __DIR__ . '/../..' . '/kirki-packages/control-custom/src', + 7 => __DIR__ . '/../..' . '/kirki-packages/control-dashicons/src', + 8 => __DIR__ . '/../..' . '/kirki-packages/control-date/src', + 9 => __DIR__ . '/../..' . '/kirki-packages/control-dimension/src', + 10 => __DIR__ . '/../..' . '/kirki-packages/control-editor/src', + 11 => __DIR__ . '/../..' . '/kirki-packages/control-generic/src', + 12 => __DIR__ . '/../..' . '/kirki-packages/control-image/src', + 13 => __DIR__ . '/../..' . '/kirki-packages/control-multicheck/src', + 14 => __DIR__ . '/../..' . '/kirki-packages/control-palette/src', + 15 => __DIR__ . '/../..' . '/kirki-packages/control-radio/src', + 16 => __DIR__ . '/../..' . '/kirki-packages/control-react-colorful/src', + 17 => __DIR__ . '/../..' . '/kirki-packages/control-react-select/src', + 18 => __DIR__ . '/../..' . '/kirki-packages/control-repeater/src', + 19 => __DIR__ . '/../..' . '/kirki-packages/control-select/src', + 20 => __DIR__ . '/../..' . '/kirki-packages/control-slider/src', + 21 => __DIR__ . '/../..' . '/kirki-packages/control-sortable/src', + 22 => __DIR__ . '/../..' . '/kirki-packages/control-upload/src', + 23 => __DIR__ . '/../..' . '/kirki-packages/field/src', + 24 => __DIR__ . '/../..' . '/kirki-packages/googlefonts/src', + 25 => __DIR__ . '/../..' . '/kirki-packages/l10n/src', + 26 => __DIR__ . '/../..' . '/kirki-packages/module-panels/src', + 27 => __DIR__ . '/../..' . '/kirki-packages/module-sections/src', + 28 => __DIR__ . '/../..' . '/kirki-packages/url-getter/src', + ), + 'Composer\\Installers\\' => + array ( + 0 => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit734b74506bf23405b8270b65bdba2dd6::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit734b74506bf23405b8270b65bdba2dd6::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit734b74506bf23405b8270b65bdba2dd6::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/include_paths.php b/kirki-composer/composer/include_paths.php similarity index 100% rename from vendor/composer/include_paths.php rename to kirki-composer/composer/include_paths.php diff --git a/vendor/composer/installed.json b/kirki-composer/composer/installed.json similarity index 100% rename from vendor/composer/installed.json rename to kirki-composer/composer/installed.json diff --git a/vendor/composer/installed.php b/kirki-composer/composer/installed.php similarity index 100% rename from vendor/composer/installed.php rename to kirki-composer/composer/installed.php diff --git a/kirki-composer/composer/installers/.github/workflows/continuous-integration.yml b/kirki-composer/composer/installers/.github/workflows/continuous-integration.yml new file mode 100644 index 000000000..037825707 --- /dev/null +++ b/kirki-composer/composer/installers/.github/workflows/continuous-integration.yml @@ -0,0 +1,62 @@ +name: "Continuous Integration" + +on: + - push + - pull_request + +env: + COMPOSER_FLAGS: "--ansi --no-interaction --no-progress --prefer-dist" + SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT: "1" + +jobs: + tests: + name: "CI" + + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + dependencies: [locked] + include: + - php-version: "7.2" + dependencies: lowest + - php-version: "8.1" + dependencies: lowest + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + tools: composer:snapshot + + - name: Get composer cache directory + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: "Handle lowest dependencies update" + if: "contains(matrix.dependencies, 'lowest')" + run: "echo \"COMPOSER_FLAGS=$COMPOSER_FLAGS --prefer-lowest\" >> $GITHUB_ENV" + + - name: "Install latest dependencies" + run: "composer update ${{ env.COMPOSER_FLAGS }}" + + - name: "Run tests" + run: "vendor/bin/simple-phpunit --verbose" diff --git a/kirki-composer/composer/installers/.github/workflows/lint.yml b/kirki-composer/composer/installers/.github/workflows/lint.yml new file mode 100644 index 000000000..843ac352b --- /dev/null +++ b/kirki-composer/composer/installers/.github/workflows/lint.yml @@ -0,0 +1,30 @@ +name: "PHP Lint" + +on: + - push + - pull_request + +jobs: + tests: + name: "Lint" + + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: + - "7.2" + - "latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + + - name: "Lint PHP files" + run: "find src/ -type f -name '*.php' -print0 | xargs -0 -L1 -P4 -- php -l -f" diff --git a/kirki-composer/composer/installers/.github/workflows/phpstan.yml b/kirki-composer/composer/installers/.github/workflows/phpstan.yml new file mode 100644 index 000000000..559fae1db --- /dev/null +++ b/kirki-composer/composer/installers/.github/workflows/phpstan.yml @@ -0,0 +1,49 @@ +name: "PHPStan" + +on: + - push + - pull_request + +env: + COMPOSER_FLAGS: "--ansi --no-interaction --no-progress --prefer-dist" + SYMFONY_PHPUNIT_VERSION: "" + +jobs: + tests: + name: "PHPStan" + + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: + - "8.0" + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + + - name: Get composer cache directory + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: "Install latest dependencies" + run: "composer update ${{ env.COMPOSER_FLAGS }}" + + - name: Run PHPStan + run: | + composer require --dev phpunit/phpunit:^8.5.18 --with-all-dependencies ${{ env.COMPOSER_FLAGS }} + vendor/bin/phpstan analyse diff --git a/kirki-composer/composer/installers/LICENSE b/kirki-composer/composer/installers/LICENSE new file mode 100644 index 000000000..85f97fc79 --- /dev/null +++ b/kirki-composer/composer/installers/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Kyle Robinson Young + +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. \ No newline at end of file diff --git a/kirki-composer/composer/installers/composer.json b/kirki-composer/composer/installers/composer.json new file mode 100644 index 000000000..5745d3bca --- /dev/null +++ b/kirki-composer/composer/installers/composer.json @@ -0,0 +1,116 @@ +{ + "name": "composer/installers", + "type": "composer-plugin", + "license": "MIT", + "description": "A multi-framework Composer library installer", + "keywords": [ + "installer", + "AGL", + "AnnotateCms", + "Attogram", + "Bitrix", + "CakePHP", + "Chef", + "Cockpit", + "CodeIgniter", + "concrete5", + "Croogo", + "DokuWiki", + "Dolibarr", + "Drupal", + "Elgg", + "Eliasis", + "ExpressionEngine", + "eZ Platform", + "FuelPHP", + "Grav", + "Hurad", + "ImageCMS", + "iTop", + "Kanboard", + "Known", + "Kohana", + "Lan Management System", + "Laravel", + "Lavalite", + "Lithium", + "Magento", + "majima", + "Mako", + "MantisBT", + "Matomo", + "Mautic", + "Maya", + "MODX", + "MODX Evo", + "MediaWiki", + "Miaoxing", + "OXID", + "osclass", + "MODULEWork", + "Moodle", + "Pantheon", + "Piwik", + "pxcms", + "phpBB", + "Plentymarkets", + "PPI", + "Puppet", + "Porto", + "ProcessWire", + "RadPHP", + "ReIndex", + "Roundcube", + "shopware", + "SilverStripe", + "SMF", + "Starbug", + "SyDES", + "Sylius", + "TastyIgniter", + "Thelia", + "WHMCS", + "WolfCMS", + "WordPress", + "YAWIK", + "Zend", + "Zikula" + ], + "homepage": "https://composer.github.io/installers/", + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "autoload": { + "psr-4": { "Composer\\Installers\\": "src/Composer/Installers" } + }, + "autoload-dev": { + "psr-4": { "Composer\\Installers\\Test\\": "tests/Composer/Installers/Test" } + }, + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-main": "2.x-dev" + }, + "plugin-modifies-install-path": true + }, + "require": { + "php": "^7.2 || ^8.0", + "composer-plugin-api": "^1.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "1.6.* || ^2.0", + "composer/semver": "^1 || ^3", + "symfony/phpunit-bridge": "^5.3", + "phpstan/phpstan": "^0.12.55", + "symfony/process": "^5", + "phpstan/phpstan-phpunit": "^0.12.16" + }, + "scripts": { + "test": "vendor/bin/simple-phpunit", + "phpstan": "vendor/bin/phpstan analyse" + } +} diff --git a/kirki-composer/composer/installers/phpstan.neon.dist b/kirki-composer/composer/installers/phpstan.neon.dist new file mode 100644 index 000000000..b15782acf --- /dev/null +++ b/kirki-composer/composer/installers/phpstan.neon.dist @@ -0,0 +1,12 @@ +parameters: + level: 8 + paths: + - src + - tests + excludes_analyse: + - tests/Composer/Installers/Test/PolyfillTestCase.php + ignoreErrors: + - '~Test::[a-zA-Z0-9]+Provider\(\) return type~' + +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon diff --git a/kirki-composer/composer/installers/src/Composer/Installers/AglInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/AglInstaller.php new file mode 100644 index 000000000..b0996a6ae --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/AglInstaller.php @@ -0,0 +1,29 @@ + */ + protected $locations = array( + 'module' => 'More/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $name = preg_replace_callback('/(?:^|_|-)(.?)/', function ($matches) { + return strtoupper($matches[1]); + }, $vars['name']); + + if (null === $name) { + throw new \RuntimeException('Failed to run preg_replace_callback: '.preg_last_error()); + } + + $vars['name'] = $name; + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/AkauntingInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/AkauntingInstaller.php new file mode 100644 index 000000000..c504c70f3 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/AkauntingInstaller.php @@ -0,0 +1,23 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php new file mode 100644 index 000000000..58a0f6669 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'module' => 'addons/modules/{$name}/', + 'component' => 'addons/components/{$name}/', + 'service' => 'addons/services/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/AsgardInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/AsgardInstaller.php new file mode 100644 index 000000000..f01b3991d --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/AsgardInstaller.php @@ -0,0 +1,58 @@ + */ + protected $locations = array( + 'module' => 'Modules/{$name}/', + 'theme' => 'Themes/{$name}/' + ); + + /** + * Format package name. + * + * For package type asgard-module, cut off a trailing '-plugin' if present. + * + * For package type asgard-theme, cut off a trailing '-theme' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'asgard-module') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'asgard-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectPluginVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-module$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectThemeVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-theme$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/AttogramInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/AttogramInstaller.php new file mode 100644 index 000000000..bd7dd8d76 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/AttogramInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/BaseInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/BaseInstaller.php new file mode 100644 index 000000000..663ec2afd --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/BaseInstaller.php @@ -0,0 +1,137 @@ + */ + protected $locations = array(); + /** @var Composer */ + protected $composer; + /** @var PackageInterface */ + protected $package; + /** @var IOInterface */ + protected $io; + + /** + * Initializes base installer. + */ + public function __construct(PackageInterface $package, Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->package = $package; + $this->io = $io; + } + + /** + * Return the install path based on package type. + */ + public function getInstallPath(PackageInterface $package, string $frameworkType = ''): string + { + $type = $this->package->getType(); + + $prettyName = $this->package->getPrettyName(); + if (strpos($prettyName, '/') !== false) { + list($vendor, $name) = explode('/', $prettyName); + } else { + $vendor = ''; + $name = $prettyName; + } + + $availableVars = $this->inflectPackageVars(compact('name', 'vendor', 'type')); + + $extra = $package->getExtra(); + if (!empty($extra['installer-name'])) { + $availableVars['name'] = $extra['installer-name']; + } + + $extra = $this->composer->getPackage()->getExtra(); + if (!empty($extra['installer-paths'])) { + $customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type, $vendor); + if ($customPath !== false) { + return $this->templatePath($customPath, $availableVars); + } + } + + $packageType = substr($type, strlen($frameworkType) + 1); + $locations = $this->getLocations($frameworkType); + if (!isset($locations[$packageType])) { + throw new \InvalidArgumentException(sprintf('Package type "%s" is not supported', $type)); + } + + return $this->templatePath($locations[$packageType], $availableVars); + } + + /** + * For an installer to override to modify the vars per installer. + * + * @param array $vars This will normally receive array{name: string, vendor: string, type: string} + * @return array + */ + public function inflectPackageVars(array $vars): array + { + return $vars; + } + + /** + * Gets the installer's locations + * + * @return array map of package types => install path + */ + public function getLocations(string $frameworkType) + { + return $this->locations; + } + + /** + * Replace vars in a path + * + * @param array $vars + */ + protected function templatePath(string $path, array $vars = array()): string + { + if (strpos($path, '{') !== false) { + extract($vars); + preg_match_all('@\{\$([A-Za-z0-9_]*)\}@i', $path, $matches); + if (!empty($matches[1])) { + foreach ($matches[1] as $var) { + $path = str_replace('{$' . $var . '}', $$var, $path); + } + } + } + + return $path; + } + + /** + * Search through a passed paths array for a custom install path. + * + * @param array $paths + * @return string|false + */ + protected function mapCustomInstallPaths(array $paths, string $name, string $type, ?string $vendor = null) + { + foreach ($paths as $path => $names) { + $names = (array) $names; + if (in_array($name, $names) || in_array('type:' . $type, $names) || in_array('vendor:' . $vendor, $names)) { + return $path; + } + } + + return false; + } + + protected function pregReplace(string $pattern, string $replacement, string $subject): string + { + $result = preg_replace($pattern, $replacement, $subject); + if (null === $result) { + throw new \RuntimeException('Failed to run preg_replace with '.$pattern.': '.preg_last_error()); + } + + return $result; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/BitrixInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/BitrixInstaller.php new file mode 100644 index 000000000..705ecb4fa --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/BitrixInstaller.php @@ -0,0 +1,123 @@ +.`. + * - `bitrix-d7-component` — copy the component to directory `bitrix/components//`. + * - `bitrix-d7-template` — copy the template to directory `bitrix/templates/_`. + * + * You can set custom path to directory with Bitrix kernel in `composer.json`: + * + * ```json + * { + * "extra": { + * "bitrix-dir": "s1/bitrix" + * } + * } + * ``` + * + * @author Nik Samokhvalov + * @author Denis Kulichkin + */ +class BitrixInstaller extends BaseInstaller +{ + /** @var array */ + protected $locations = array( + 'module' => '{$bitrix_dir}/modules/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) + 'component' => '{$bitrix_dir}/components/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) + 'theme' => '{$bitrix_dir}/templates/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) + 'd7-module' => '{$bitrix_dir}/modules/{$vendor}.{$name}/', + 'd7-component' => '{$bitrix_dir}/components/{$vendor}/{$name}/', + 'd7-template' => '{$bitrix_dir}/templates/{$vendor}_{$name}/', + ); + + /** + * @var string[] Storage for informations about duplicates at all the time of installation packages. + */ + private static $checkedDuplicates = array(); + + public function inflectPackageVars(array $vars): array + { + /** @phpstan-ignore-next-line */ + if ($this->composer->getPackage()) { + $extra = $this->composer->getPackage()->getExtra(); + + if (isset($extra['bitrix-dir'])) { + $vars['bitrix_dir'] = $extra['bitrix-dir']; + } + } + + if (!isset($vars['bitrix_dir'])) { + $vars['bitrix_dir'] = 'bitrix'; + } + + return parent::inflectPackageVars($vars); + } + + /** + * {@inheritdoc} + */ + protected function templatePath(string $path, array $vars = array()): string + { + $templatePath = parent::templatePath($path, $vars); + $this->checkDuplicates($templatePath, $vars); + + return $templatePath; + } + + /** + * Duplicates search packages. + * + * @param array $vars + */ + protected function checkDuplicates(string $path, array $vars = array()): void + { + $packageType = substr($vars['type'], strlen('bitrix') + 1); + $localDir = explode('/', $vars['bitrix_dir']); + array_pop($localDir); + $localDir[] = 'local'; + $localDir = implode('/', $localDir); + + $oldPath = str_replace( + array('{$bitrix_dir}', '{$name}'), + array($localDir, $vars['name']), + $this->locations[$packageType] + ); + + if (in_array($oldPath, static::$checkedDuplicates)) { + return; + } + + if ($oldPath !== $path && file_exists($oldPath) && $this->io->isInteractive()) { + $this->io->writeError(' Duplication of packages:'); + $this->io->writeError(' Package ' . $oldPath . ' will be called instead package ' . $path . ''); + + while (true) { + switch ($this->io->ask(' Delete ' . $oldPath . ' [y,n,?]? ', '?')) { + case 'y': + $fs = new Filesystem(); + $fs->removeDirectory($oldPath); + break 2; + + case 'n': + break 2; + + case '?': + default: + $this->io->writeError(array( + ' y - delete package ' . $oldPath . ' and to continue with the installation', + ' n - don\'t delete and to continue with the installation', + )); + $this->io->writeError(' ? - print help'); + break; + } + } + } + + static::$checkedDuplicates[] = $oldPath; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/BonefishInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/BonefishInstaller.php new file mode 100644 index 000000000..ab022d995 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/BonefishInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'package' => 'Packages/{$vendor}/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/CakePHPInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/CakePHPInstaller.php new file mode 100644 index 000000000..df45895b8 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/CakePHPInstaller.php @@ -0,0 +1,67 @@ + */ + protected $locations = array( + 'plugin' => 'Plugin/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + if ($this->matchesCakeVersion('>=', '3.0.0')) { + return $vars; + } + + $nameParts = explode('/', $vars['name']); + foreach ($nameParts as &$value) { + $value = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $value)); + $value = str_replace(array('-', '_'), ' ', $value); + $value = str_replace(' ', '', ucwords($value)); + } + $vars['name'] = implode('/', $nameParts); + + return $vars; + } + + /** + * Change the default plugin location when cakephp >= 3.0 + */ + public function getLocations(string $frameworkType): array + { + if ($this->matchesCakeVersion('>=', '3.0.0')) { + $this->locations['plugin'] = $this->composer->getConfig()->get('vendor-dir') . '/{$vendor}/{$name}/'; + } + return $this->locations; + } + + /** + * Check if CakePHP version matches against a version + * + * @phpstan-param Constraint::STR_OP_* $matcher + */ + protected function matchesCakeVersion(string $matcher, string $version): bool + { + $repositoryManager = $this->composer->getRepositoryManager(); + /** @phpstan-ignore-next-line */ + if (!$repositoryManager) { + return false; + } + + $repos = $repositoryManager->getLocalRepository(); + /** @phpstan-ignore-next-line */ + if (!$repos) { + return false; + } + + return $repos->findPackage('cakephp/cakephp', new Constraint($matcher, $version)) !== null; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ChefInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ChefInstaller.php new file mode 100644 index 000000000..b0d3c5f76 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ChefInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'cookbook' => 'Chef/{$vendor}/{$name}/', + 'role' => 'Chef/roles/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/CiviCrmInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/CiviCrmInstaller.php new file mode 100644 index 000000000..1c52e0cdc --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/CiviCrmInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'ext' => 'ext/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php new file mode 100644 index 000000000..2c943b215 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'ship' => 'CCF/orbit/{$name}/', + 'theme' => 'CCF/app/themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/CockpitInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/CockpitInstaller.php new file mode 100644 index 000000000..d3fcdf7d4 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/CockpitInstaller.php @@ -0,0 +1,36 @@ + */ + protected $locations = array( + 'module' => 'cockpit/modules/addons/{$name}/', + ); + + /** + * Format module name. + * + * Strip `module-` prefix from package name. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] == 'cockpit-module') { + return $this->inflectModuleVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + public function inflectModuleVars(array $vars): array + { + $vars['name'] = ucfirst($this->pregReplace('/cockpit-/i', '', $vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php new file mode 100644 index 000000000..a183e0781 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'library' => 'application/libraries/{$name}/', + 'third-party' => 'application/third_party/{$name}/', + 'module' => 'application/modules/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/Concrete5Installer.php b/kirki-composer/composer/installers/src/Composer/Installers/Concrete5Installer.php new file mode 100644 index 000000000..2f5fecb3d --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/Concrete5Installer.php @@ -0,0 +1,15 @@ + */ + protected $locations = array( + 'core' => 'concrete/', + 'block' => 'application/blocks/{$name}/', + 'package' => 'packages/{$name}/', + 'theme' => 'application/themes/{$name}/', + 'update' => 'updates/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/CroogoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/CroogoInstaller.php new file mode 100644 index 000000000..31d4939b0 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/CroogoInstaller.php @@ -0,0 +1,23 @@ + */ + protected $locations = array( + 'plugin' => 'Plugin/{$name}/', + 'theme' => 'View/Themed/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower(str_replace(array('-', '_'), ' ', $vars['name'])); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/DecibelInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/DecibelInstaller.php new file mode 100644 index 000000000..88f53f731 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/DecibelInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'app' => 'app/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/DframeInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/DframeInstaller.php new file mode 100644 index 000000000..196f60efa --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/DframeInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'module' => 'modules/{$vendor}/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/DokuWikiInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/DokuWikiInstaller.php new file mode 100644 index 000000000..aa3a2e600 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/DokuWikiInstaller.php @@ -0,0 +1,57 @@ + */ + protected $locations = array( + 'plugin' => 'lib/plugins/{$name}/', + 'template' => 'lib/tpl/{$name}/', + ); + + /** + * Format package name. + * + * For package type dokuwiki-plugin, cut off a trailing '-plugin', + * or leading dokuwiki_ if present. + * + * For package type dokuwiki-template, cut off a trailing '-template' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'dokuwiki-plugin') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'dokuwiki-template') { + return $this->inflectTemplateVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectPluginVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-plugin$/', '', $vars['name']); + $vars['name'] = $this->pregReplace('/^dokuwiki_?-?/', '', $vars['name']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectTemplateVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-template$/', '', $vars['name']); + $vars['name'] = $this->pregReplace('/^dokuwiki_?-?/', '', $vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/DolibarrInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/DolibarrInstaller.php new file mode 100644 index 000000000..c583619ca --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/DolibarrInstaller.php @@ -0,0 +1,18 @@ + + */ +class DolibarrInstaller extends BaseInstaller +{ + //TODO: Add support for scripts and themes + /** @var array */ + protected $locations = array( + 'module' => 'htdocs/custom/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/DrupalInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/DrupalInstaller.php new file mode 100644 index 000000000..7690f3069 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/DrupalInstaller.php @@ -0,0 +1,24 @@ + */ + protected $locations = array( + 'core' => 'core/', + 'module' => 'modules/{$name}/', + 'theme' => 'themes/{$name}/', + 'library' => 'libraries/{$name}/', + 'profile' => 'profiles/{$name}/', + 'database-driver' => 'drivers/lib/Drupal/Driver/Database/{$name}/', + 'drush' => 'drush/{$name}/', + 'custom-theme' => 'themes/custom/{$name}/', + 'custom-module' => 'modules/custom/{$name}/', + 'custom-profile' => 'profiles/custom/{$name}/', + 'drupal-multisite' => 'sites/{$name}/', + 'console' => 'console/{$name}/', + 'console-language' => 'console/language/{$name}/', + 'config' => 'config/sync/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ElggInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ElggInstaller.php new file mode 100644 index 000000000..48ef2ecdd --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ElggInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'plugin' => 'mod/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/EliasisInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/EliasisInstaller.php new file mode 100644 index 000000000..d7dd9a922 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/EliasisInstaller.php @@ -0,0 +1,14 @@ + */ + protected $locations = array( + 'component' => 'components/{$name}/', + 'module' => 'modules/{$name}/', + 'plugin' => 'plugins/{$name}/', + 'template' => 'templates/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php new file mode 100644 index 000000000..fe1d468a9 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php @@ -0,0 +1,31 @@ + */ + private $ee2Locations = array( + 'addon' => 'system/expressionengine/third_party/{$name}/', + 'theme' => 'themes/third_party/{$name}/', + ); + + /** @var array */ + private $ee3Locations = array( + 'addon' => 'system/user/addons/{$name}/', + 'theme' => 'themes/user/{$name}/', + ); + + public function getLocations(string $frameworkType): array + { + if ($frameworkType === 'ee2') { + $this->locations = $this->ee2Locations; + } else { + $this->locations = $this->ee3Locations; + } + + return $this->locations; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/EzPlatformInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/EzPlatformInstaller.php new file mode 100644 index 000000000..1f5b84e2a --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/EzPlatformInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'meta-assets' => 'web/assets/ezplatform/', + 'assets' => 'web/assets/ezplatform/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/FuelInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/FuelInstaller.php new file mode 100644 index 000000000..5948572e2 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/FuelInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'module' => 'fuel/app/modules/{$name}/', + 'package' => 'fuel/packages/{$name}/', + 'theme' => 'fuel/app/themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/FuelphpInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/FuelphpInstaller.php new file mode 100644 index 000000000..b4d80ed31 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/FuelphpInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'component' => 'components/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/GravInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/GravInstaller.php new file mode 100644 index 000000000..f5792e36b --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/GravInstaller.php @@ -0,0 +1,29 @@ + */ + protected $locations = array( + 'plugin' => 'user/plugins/{$name}/', + 'theme' => 'user/themes/{$name}/', + ); + + /** + * Format package name + */ + public function inflectPackageVars(array $vars): array + { + $restrictedWords = implode('|', array_keys($this->locations)); + + $vars['name'] = strtolower($vars['name']); + $vars['name'] = $this->pregReplace( + '/^(?:grav-)?(?:(?:'.$restrictedWords.')-)?(.*?)(?:-(?:'.$restrictedWords.'))?$/ui', + '$1', + $vars['name'] + ); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/HuradInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/HuradInstaller.php new file mode 100644 index 000000000..dd76c5b68 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/HuradInstaller.php @@ -0,0 +1,27 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + 'theme' => 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $nameParts = explode('/', $vars['name']); + foreach ($nameParts as &$value) { + $value = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $value)); + $value = str_replace(array('-', '_'), ' ', $value); + $value = str_replace(' ', '', ucwords($value)); + } + $vars['name'] = implode('/', $nameParts); + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ImageCMSInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ImageCMSInstaller.php new file mode 100644 index 000000000..4157cecac --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ImageCMSInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'template' => 'templates/{$name}/', + 'module' => 'application/modules/{$name}/', + 'library' => 'application/libraries/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/Installer.php b/kirki-composer/composer/installers/src/Composer/Installers/Installer.php new file mode 100644 index 000000000..67a73e9d2 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/Installer.php @@ -0,0 +1,280 @@ + + */ + private $supportedTypes = array( + 'akaunting' => 'AkauntingInstaller', + 'asgard' => 'AsgardInstaller', + 'attogram' => 'AttogramInstaller', + 'agl' => 'AglInstaller', + 'annotatecms' => 'AnnotateCmsInstaller', + 'bitrix' => 'BitrixInstaller', + 'bonefish' => 'BonefishInstaller', + 'cakephp' => 'CakePHPInstaller', + 'chef' => 'ChefInstaller', + 'civicrm' => 'CiviCrmInstaller', + 'ccframework' => 'ClanCatsFrameworkInstaller', + 'cockpit' => 'CockpitInstaller', + 'codeigniter' => 'CodeIgniterInstaller', + 'concrete5' => 'Concrete5Installer', + 'croogo' => 'CroogoInstaller', + 'dframe' => 'DframeInstaller', + 'dokuwiki' => 'DokuWikiInstaller', + 'dolibarr' => 'DolibarrInstaller', + 'decibel' => 'DecibelInstaller', + 'drupal' => 'DrupalInstaller', + 'elgg' => 'ElggInstaller', + 'eliasis' => 'EliasisInstaller', + 'ee3' => 'ExpressionEngineInstaller', + 'ee2' => 'ExpressionEngineInstaller', + 'ezplatform' => 'EzPlatformInstaller', + 'fuel' => 'FuelInstaller', + 'fuelphp' => 'FuelphpInstaller', + 'grav' => 'GravInstaller', + 'hurad' => 'HuradInstaller', + 'tastyigniter' => 'TastyIgniterInstaller', + 'imagecms' => 'ImageCMSInstaller', + 'itop' => 'ItopInstaller', + 'kanboard' => 'KanboardInstaller', + 'known' => 'KnownInstaller', + 'kodicms' => 'KodiCMSInstaller', + 'kohana' => 'KohanaInstaller', + 'lms' => 'LanManagementSystemInstaller', + 'laravel' => 'LaravelInstaller', + 'lavalite' => 'LavaLiteInstaller', + 'lithium' => 'LithiumInstaller', + 'magento' => 'MagentoInstaller', + 'majima' => 'MajimaInstaller', + 'mantisbt' => 'MantisBTInstaller', + 'mako' => 'MakoInstaller', + 'matomo' => 'MatomoInstaller', + 'maya' => 'MayaInstaller', + 'mautic' => 'MauticInstaller', + 'mediawiki' => 'MediaWikiInstaller', + 'miaoxing' => 'MiaoxingInstaller', + 'microweber' => 'MicroweberInstaller', + 'modulework' => 'MODULEWorkInstaller', + 'modx' => 'ModxInstaller', + 'modxevo' => 'MODXEvoInstaller', + 'moodle' => 'MoodleInstaller', + 'october' => 'OctoberInstaller', + 'ontowiki' => 'OntoWikiInstaller', + 'oxid' => 'OxidInstaller', + 'osclass' => 'OsclassInstaller', + 'pxcms' => 'PxcmsInstaller', + 'phpbb' => 'PhpBBInstaller', + 'piwik' => 'PiwikInstaller', + 'plentymarkets'=> 'PlentymarketsInstaller', + 'ppi' => 'PPIInstaller', + 'puppet' => 'PuppetInstaller', + 'radphp' => 'RadPHPInstaller', + 'phifty' => 'PhiftyInstaller', + 'porto' => 'PortoInstaller', + 'processwire' => 'ProcessWireInstaller', + 'quicksilver' => 'PantheonInstaller', + 'redaxo' => 'RedaxoInstaller', + 'redaxo5' => 'Redaxo5Installer', + 'reindex' => 'ReIndexInstaller', + 'roundcube' => 'RoundcubeInstaller', + 'shopware' => 'ShopwareInstaller', + 'sitedirect' => 'SiteDirectInstaller', + 'silverstripe' => 'SilverStripeInstaller', + 'smf' => 'SMFInstaller', + 'starbug' => 'StarbugInstaller', + 'sydes' => 'SyDESInstaller', + 'sylius' => 'SyliusInstaller', + 'tao' => 'TaoInstaller', + 'thelia' => 'TheliaInstaller', + 'tusk' => 'TuskInstaller', + 'userfrosting' => 'UserFrostingInstaller', + 'vanilla' => 'VanillaInstaller', + 'whmcs' => 'WHMCSInstaller', + 'winter' => 'WinterInstaller', + 'wolfcms' => 'WolfCMSInstaller', + 'wordpress' => 'WordPressInstaller', + 'yawik' => 'YawikInstaller', + 'zend' => 'ZendInstaller', + 'zikula' => 'ZikulaInstaller', + 'prestashop' => 'PrestashopInstaller' + ); + + /** + * Disables installers specified in main composer extra installer-disable + * list + */ + public function __construct( + IOInterface $io, + Composer $composer, + string $type = 'library', + ?Filesystem $filesystem = null, + ?BinaryInstaller $binaryInstaller = null + ) { + parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller); + $this->removeDisabledInstallers(); + } + + /** + * {@inheritDoc} + */ + public function getInstallPath(PackageInterface $package) + { + $type = $package->getType(); + $frameworkType = $this->findFrameworkType($type); + + if ($frameworkType === false) { + throw new \InvalidArgumentException( + 'Sorry the package type of this package is not yet supported.' + ); + } + + $class = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType]; + $installer = new $class($package, $this->composer, $this->getIO()); + + $path = $installer->getInstallPath($package, $frameworkType); + if (!$this->filesystem->isAbsolutePath($path)) { + $path = getcwd() . '/' . $path; + } + + return $path; + } + + public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) + { + $installPath = $this->getPackageBasePath($package); + $io = $this->io; + $outputStatus = function () use ($io, $installPath) { + $io->write(sprintf('Deleting %s - %s', $installPath, !file_exists($installPath) ? 'deleted' : 'not deleted')); + }; + + $promise = parent::uninstall($repo, $package); + + // Composer v2 might return a promise here + if ($promise instanceof PromiseInterface) { + return $promise->then($outputStatus); + } + + // If not, execute the code right away as parent::uninstall executed synchronously (composer v1, or v2 without async) + $outputStatus(); + + return null; + } + + /** + * {@inheritDoc} + */ + public function supports($packageType) + { + $frameworkType = $this->findFrameworkType($packageType); + + if ($frameworkType === false) { + return false; + } + + $locationPattern = $this->getLocationPattern($frameworkType); + + return preg_match('#' . $frameworkType . '-' . $locationPattern . '#', $packageType, $matches) === 1; + } + + /** + * Finds a supported framework type if it exists and returns it + * + * @return string|false + */ + protected function findFrameworkType(string $type) + { + krsort($this->supportedTypes); + + foreach ($this->supportedTypes as $key => $val) { + if ($key === substr($type, 0, strlen($key))) { + return substr($type, 0, strlen($key)); + } + } + + return false; + } + + /** + * Get the second part of the regular expression to check for support of a + * package type + */ + protected function getLocationPattern(string $frameworkType): string + { + $pattern = null; + if (!empty($this->supportedTypes[$frameworkType])) { + $frameworkClass = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType]; + /** @var BaseInstaller $framework */ + $framework = new $frameworkClass(new Package('dummy/pkg', '1.0.0.0', '1.0.0'), $this->composer, $this->getIO()); + $locations = array_keys($framework->getLocations($frameworkType)); + if ($locations) { + $pattern = '(' . implode('|', $locations) . ')'; + } + } + + return $pattern ?: '(\w+)'; + } + + private function getIO(): IOInterface + { + return $this->io; + } + + /** + * Look for installers set to be disabled in composer's extra config and + * remove them from the list of supported installers. + * + * Globals: + * - true, "all", and "*" - disable all installers. + * - false - enable all installers (useful with + * wikimedia/composer-merge-plugin or similar) + */ + protected function removeDisabledInstallers(): void + { + $extra = $this->composer->getPackage()->getExtra(); + + if (!isset($extra['installer-disable']) || $extra['installer-disable'] === false) { + // No installers are disabled + return; + } + + // Get installers to disable + $disable = $extra['installer-disable']; + + // Ensure $disabled is an array + if (!is_array($disable)) { + $disable = array($disable); + } + + // Check which installers should be disabled + $all = array(true, "all", "*"); + $intersect = array_intersect($all, $disable); + if (!empty($intersect)) { + // Disable all installers + $this->supportedTypes = array(); + return; + } + + // Disable specified installers + foreach ($disable as $key => $installer) { + if (is_string($installer) && key_exists($installer, $this->supportedTypes)) { + unset($this->supportedTypes[$installer]); + } + } + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ItopInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ItopInstaller.php new file mode 100644 index 000000000..06af06870 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ItopInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'extension' => 'extensions/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/KanboardInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/KanboardInstaller.php new file mode 100644 index 000000000..bca954b28 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/KanboardInstaller.php @@ -0,0 +1,20 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/KnownInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/KnownInstaller.php new file mode 100644 index 000000000..61910a86b --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/KnownInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'plugin' => 'IdnoPlugins/{$name}/', + 'theme' => 'Themes/{$name}/', + 'console' => 'ConsolePlugins/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/KodiCMSInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/KodiCMSInstaller.php new file mode 100644 index 000000000..2505ac688 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/KodiCMSInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'plugin' => 'cms/plugins/{$name}/', + 'media' => 'cms/media/vendor/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/KohanaInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/KohanaInstaller.php new file mode 100644 index 000000000..b6aa8097c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/KohanaInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php new file mode 100644 index 000000000..7fe9d9b79 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php @@ -0,0 +1,27 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + 'template' => 'templates/{$name}/', + 'document-template' => 'documents/templates/{$name}/', + 'userpanel-module' => 'userpanel/modules/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/LaravelInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/LaravelInstaller.php new file mode 100644 index 000000000..a69dc8890 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/LaravelInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'library' => 'libraries/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/LavaLiteInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/LavaLiteInstaller.php new file mode 100644 index 000000000..e4a7c7da8 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/LavaLiteInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'package' => 'packages/{$vendor}/{$name}/', + 'theme' => 'public/themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/LithiumInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/LithiumInstaller.php new file mode 100644 index 000000000..b24bea20c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/LithiumInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'library' => 'libraries/{$name}/', + 'source' => 'libraries/_source/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php new file mode 100644 index 000000000..369e8b45c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MODXEvoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MODXEvoInstaller.php new file mode 100644 index 000000000..062a839ba --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MODXEvoInstaller.php @@ -0,0 +1,18 @@ + */ + protected $locations = array( + 'snippet' => 'assets/snippets/{$name}/', + 'plugin' => 'assets/plugins/{$name}/', + 'module' => 'assets/modules/{$name}/', + 'template' => 'assets/templates/{$name}/', + 'lib' => 'assets/lib/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MagentoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MagentoInstaller.php new file mode 100644 index 000000000..ec07cd64e --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MagentoInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'theme' => 'app/design/frontend/{$name}/', + 'skin' => 'skin/frontend/default/{$name}/', + 'library' => 'lib/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MajimaInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MajimaInstaller.php new file mode 100644 index 000000000..6fc3089d2 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MajimaInstaller.php @@ -0,0 +1,46 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); + + /** + * Transforms the names + * + * @param array $vars + * @return array + */ + public function inflectPackageVars(array $vars): array + { + return $this->correctPluginName($vars); + } + + /** + * Change hyphenated names to camelcase + * + * @param array $vars + * @return array + */ + private function correctPluginName(array $vars): array + { + $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) { + return strtoupper($matches[0][1]); + }, $vars['name']); + + if (null === $camelCasedName) { + throw new \RuntimeException('Failed to run preg_replace_callback: '.preg_last_error()); + } + + $vars['name'] = ucfirst($camelCasedName); + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MakoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MakoInstaller.php new file mode 100644 index 000000000..cbe3760ba --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MakoInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'package' => 'app/packages/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MantisBTInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MantisBTInstaller.php new file mode 100644 index 000000000..98e230fb4 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MantisBTInstaller.php @@ -0,0 +1,25 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MatomoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MatomoInstaller.php new file mode 100644 index 000000000..57fdb0330 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MatomoInstaller.php @@ -0,0 +1,28 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MauticInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MauticInstaller.php new file mode 100644 index 000000000..e48c133b8 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MauticInstaller.php @@ -0,0 +1,43 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + 'theme' => 'themes/{$name}/', + 'core' => 'app/', + ); + + private function getDirectoryName(): string + { + $extra = $this->package->getExtra(); + if (!empty($extra['install-directory-name'])) { + return $extra['install-directory-name']; + } + + return $this->toCamelCase($this->package->getPrettyName()); + } + + private function toCamelCase(string $packageName): string + { + return str_replace(' ', '', ucwords(str_replace('-', ' ', basename($packageName)))); + } + + /** + * Format package name of mautic-plugins to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] == 'mautic-plugin' || $vars['type'] == 'mautic-theme') { + $directoryName = $this->getDirectoryName(); + $vars['name'] = $directoryName; + } + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MayaInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MayaInstaller.php new file mode 100644 index 000000000..df486dacd --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MayaInstaller.php @@ -0,0 +1,38 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + ); + + /** + * Format package name. + * + * For package type maya-module, cut off a trailing '-module' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'maya-module') { + return $this->inflectModuleVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectModuleVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-module$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MediaWikiInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MediaWikiInstaller.php new file mode 100644 index 000000000..8e9d7713e --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MediaWikiInstaller.php @@ -0,0 +1,58 @@ + */ + protected $locations = array( + 'core' => 'core/', + 'extension' => 'extensions/{$name}/', + 'skin' => 'skins/{$name}/', + ); + + /** + * Format package name. + * + * For package type mediawiki-extension, cut off a trailing '-extension' if present and transform + * to CamelCase keeping existing uppercase chars. + * + * For package type mediawiki-skin, cut off a trailing '-skin' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'mediawiki-extension') { + return $this->inflectExtensionVars($vars); + } + + if ($vars['type'] === 'mediawiki-skin') { + return $this->inflectSkinVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectExtensionVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-extension$/', '', $vars['name']); + $vars['name'] = str_replace('-', ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectSkinVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-skin$/', '', $vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MiaoxingInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MiaoxingInstaller.php new file mode 100644 index 000000000..025417798 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MiaoxingInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MicroweberInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MicroweberInstaller.php new file mode 100644 index 000000000..a4d97ab0c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MicroweberInstaller.php @@ -0,0 +1,145 @@ + */ + protected $locations = array( + 'module' => 'userfiles/modules/{$install_item_dir}/', + 'module-skin' => 'userfiles/modules/{$install_item_dir}/templates/', + 'template' => 'userfiles/templates/{$install_item_dir}/', + 'element' => 'userfiles/elements/{$install_item_dir}/', + 'vendor' => 'vendor/{$install_item_dir}/', + 'components' => 'components/{$install_item_dir}/' + ); + + /** + * Format package name. + * + * For package type microweber-module, cut off a trailing '-module' if present + * + * For package type microweber-template, cut off a trailing '-template' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($this->package->getTargetDir() !== null && $this->package->getTargetDir() !== '') { + $vars['install_item_dir'] = $this->package->getTargetDir(); + } else { + $vars['install_item_dir'] = $vars['name']; + if ($vars['type'] === 'microweber-template') { + return $this->inflectTemplateVars($vars); + } + if ($vars['type'] === 'microweber-templates') { + return $this->inflectTemplatesVars($vars); + } + if ($vars['type'] === 'microweber-core') { + return $this->inflectCoreVars($vars); + } + if ($vars['type'] === 'microweber-adapter') { + return $this->inflectCoreVars($vars); + } + if ($vars['type'] === 'microweber-module') { + return $this->inflectModuleVars($vars); + } + if ($vars['type'] === 'microweber-modules') { + return $this->inflectModulesVars($vars); + } + if ($vars['type'] === 'microweber-skin') { + return $this->inflectSkinVars($vars); + } + if ($vars['type'] === 'microweber-element' or $vars['type'] === 'microweber-elements') { + return $this->inflectElementVars($vars); + } + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectTemplateVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-template$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/template-$/', '', $vars['install_item_dir']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectTemplatesVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-templates$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/templates-$/', '', $vars['install_item_dir']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectCoreVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-providers$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/-provider$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/-adapter$/', '', $vars['install_item_dir']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectModuleVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-module$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/module-$/', '', $vars['install_item_dir']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectModulesVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-modules$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/modules-$/', '', $vars['install_item_dir']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectSkinVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-skin$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/skin-$/', '', $vars['install_item_dir']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectElementVars(array $vars): array + { + $vars['install_item_dir'] = $this->pregReplace('/-elements$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/elements-$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/-element$/', '', $vars['install_item_dir']); + $vars['install_item_dir'] = $this->pregReplace('/element-$/', '', $vars['install_item_dir']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ModxInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ModxInstaller.php new file mode 100644 index 000000000..e2dddec5e --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ModxInstaller.php @@ -0,0 +1,14 @@ + */ + protected $locations = array( + 'extra' => 'core/packages/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/MoodleInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/MoodleInstaller.php new file mode 100644 index 000000000..d9babb37c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/MoodleInstaller.php @@ -0,0 +1,67 @@ + */ + protected $locations = array( + 'mod' => 'mod/{$name}/', + 'admin_report' => 'admin/report/{$name}/', + 'atto' => 'lib/editor/atto/plugins/{$name}/', + 'tool' => 'admin/tool/{$name}/', + 'assignment' => 'mod/assignment/type/{$name}/', + 'assignsubmission' => 'mod/assign/submission/{$name}/', + 'assignfeedback' => 'mod/assign/feedback/{$name}/', + 'antivirus' => 'lib/antivirus/{$name}/', + 'auth' => 'auth/{$name}/', + 'availability' => 'availability/condition/{$name}/', + 'block' => 'blocks/{$name}/', + 'booktool' => 'mod/book/tool/{$name}/', + 'cachestore' => 'cache/stores/{$name}/', + 'cachelock' => 'cache/locks/{$name}/', + 'calendartype' => 'calendar/type/{$name}/', + 'customfield' => 'customfield/field/{$name}/', + 'fileconverter' => 'files/converter/{$name}/', + 'format' => 'course/format/{$name}/', + 'coursereport' => 'course/report/{$name}/', + 'contenttype' => 'contentbank/contenttype/{$name}/', + 'customcertelement' => 'mod/customcert/element/{$name}/', + 'datafield' => 'mod/data/field/{$name}/', + 'dataformat' => 'dataformat/{$name}/', + 'datapreset' => 'mod/data/preset/{$name}/', + 'editor' => 'lib/editor/{$name}/', + 'enrol' => 'enrol/{$name}/', + 'filter' => 'filter/{$name}/', + 'gradeexport' => 'grade/export/{$name}/', + 'gradeimport' => 'grade/import/{$name}/', + 'gradereport' => 'grade/report/{$name}/', + 'gradingform' => 'grade/grading/form/{$name}/', + 'local' => 'local/{$name}/', + 'logstore' => 'admin/tool/log/store/{$name}/', + 'ltisource' => 'mod/lti/source/{$name}/', + 'ltiservice' => 'mod/lti/service/{$name}/', + 'media' => 'media/player/{$name}/', + 'message' => 'message/output/{$name}/', + 'mnetservice' => 'mnet/service/{$name}/', + 'paygw' => 'payment/gateway/{$name}/', + 'plagiarism' => 'plagiarism/{$name}/', + 'portfolio' => 'portfolio/{$name}/', + 'qbehaviour' => 'question/behaviour/{$name}/', + 'qformat' => 'question/format/{$name}/', + 'qtype' => 'question/type/{$name}/', + 'quizaccess' => 'mod/quiz/accessrule/{$name}/', + 'quiz' => 'mod/quiz/report/{$name}/', + 'report' => 'report/{$name}/', + 'repository' => 'repository/{$name}/', + 'scormreport' => 'mod/scorm/report/{$name}/', + 'search' => 'search/engine/{$name}/', + 'theme' => 'theme/{$name}/', + 'tinymce' => 'lib/editor/tinymce/plugins/{$name}/', + 'profilefield' => 'user/profile/field/{$name}/', + 'webservice' => 'webservice/{$name}/', + 'workshopallocation' => 'mod/workshop/allocation/{$name}/', + 'workshopeval' => 'mod/workshop/eval/{$name}/', + 'workshopform' => 'mod/workshop/form/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/OctoberInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/OctoberInstaller.php new file mode 100644 index 000000000..524f17d87 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/OctoberInstaller.php @@ -0,0 +1,57 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + 'plugin' => 'plugins/{$vendor}/{$name}/', + 'theme' => 'themes/{$vendor}-{$name}/' + ); + + /** + * Format package name. + * + * For package type october-plugin, cut off a trailing '-plugin' if present. + * + * For package type october-theme, cut off a trailing '-theme' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'october-plugin') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'october-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectPluginVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/^oc-|-plugin$/', '', $vars['name']); + $vars['vendor'] = $this->pregReplace('/[^a-z0-9_]/i', '', $vars['vendor']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectThemeVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/^oc-|-theme$/', '', $vars['name']); + $vars['vendor'] = $this->pregReplace('/[^a-z0-9_]/i', '', $vars['vendor']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/OntoWikiInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/OntoWikiInstaller.php new file mode 100644 index 000000000..fd20c1a86 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/OntoWikiInstaller.php @@ -0,0 +1,26 @@ + */ + protected $locations = array( + 'extension' => 'extensions/{$name}/', + 'theme' => 'extensions/themes/{$name}/', + 'translation' => 'extensions/translations/{$name}/', + ); + + /** + * Format package name to lower case and remove ".ontowiki" suffix + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($vars['name']); + $vars['name'] = $this->pregReplace('/.ontowiki$/', '', $vars['name']); + $vars['name'] = $this->pregReplace('/-theme$/', '', $vars['name']); + $vars['name'] = $this->pregReplace('/-translation$/', '', $vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/OsclassInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/OsclassInstaller.php new file mode 100644 index 000000000..e61d61f88 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/OsclassInstaller.php @@ -0,0 +1,14 @@ + */ + protected $locations = array( + 'plugin' => 'oc-content/plugins/{$name}/', + 'theme' => 'oc-content/themes/{$name}/', + 'language' => 'oc-content/languages/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/OxidInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/OxidInstaller.php new file mode 100644 index 000000000..6e1e8624f --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/OxidInstaller.php @@ -0,0 +1,49 @@ +.+)\/.+/'; + + /** @var array */ + protected $locations = array( + 'module' => 'modules/{$name}/', + 'theme' => 'application/views/{$name}/', + 'out' => 'out/{$name}/', + ); + + public function getInstallPath(PackageInterface $package, string $frameworkType = ''): string + { + $installPath = parent::getInstallPath($package, $frameworkType); + $type = $this->package->getType(); + if ($type === 'oxid-module') { + $this->prepareVendorDirectory($installPath); + } + return $installPath; + } + + /** + * Makes sure there is a vendormetadata.php file inside + * the vendor folder if there is a vendor folder. + */ + protected function prepareVendorDirectory(string $installPath): void + { + $matches = ''; + $hasVendorDirectory = preg_match(self::VENDOR_PATTERN, $installPath, $matches); + if (!$hasVendorDirectory) { + return; + } + + $vendorDirectory = $matches['vendor']; + $vendorPath = getcwd() . '/modules/' . $vendorDirectory; + if (!file_exists($vendorPath)) { + mkdir($vendorPath, 0755, true); + } + + $vendorMetaDataPath = $vendorPath . '/vendormetadata.php'; + touch($vendorMetaDataPath); + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PPIInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PPIInstaller.php new file mode 100644 index 000000000..714c46797 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PPIInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PantheonInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PantheonInstaller.php new file mode 100644 index 000000000..439f61a03 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PantheonInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'script' => 'web/private/scripts/quicksilver/{$name}', + 'module' => 'web/private/scripts/quicksilver/{$name}', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PhiftyInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PhiftyInstaller.php new file mode 100644 index 000000000..3c970e217 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PhiftyInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'bundle' => 'bundles/{$name}/', + 'library' => 'libraries/{$name}/', + 'framework' => 'frameworks/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PhpBBInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PhpBBInstaller.php new file mode 100644 index 000000000..d53ee4f6c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PhpBBInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'extension' => 'ext/{$vendor}/{$name}/', + 'language' => 'language/{$name}/', + 'style' => 'styles/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PiwikInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PiwikInstaller.php new file mode 100644 index 000000000..b2faf44a5 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PiwikInstaller.php @@ -0,0 +1,28 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php new file mode 100644 index 000000000..0c063598a --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php @@ -0,0 +1,28 @@ + */ + protected $locations = array( + 'plugin' => '{$name}/' + ); + + /** + * Remove hyphen, "plugin" and format to camelcase + */ + public function inflectPackageVars(array $vars): array + { + $nameBits = explode("-", $vars['name']); + foreach ($nameBits as $key => $name) { + $nameBits[$key] = ucfirst($name); + if (strcasecmp($name, "Plugin") == 0) { + unset($nameBits[$key]); + } + } + $vars['name'] = implode('', $nameBits); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/Plugin.php b/kirki-composer/composer/installers/src/Composer/Installers/Plugin.php new file mode 100644 index 000000000..437a9493a --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/Plugin.php @@ -0,0 +1,28 @@ +installer = new Installer($io, $composer); + $composer->getInstallationManager()->addInstaller($this->installer); + } + + public function deactivate(Composer $composer, IOInterface $io): void + { + $composer->getInstallationManager()->removeInstaller($this->installer); + } + + public function uninstall(Composer $composer, IOInterface $io): void + { + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PortoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PortoInstaller.php new file mode 100644 index 000000000..a01d7a0be --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PortoInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'container' => 'app/Containers/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PrestashopInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PrestashopInstaller.php new file mode 100644 index 000000000..23f156f53 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PrestashopInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + 'theme' => 'themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ProcessWireInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ProcessWireInstaller.php new file mode 100644 index 000000000..a7eb1eec6 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ProcessWireInstaller.php @@ -0,0 +1,23 @@ + */ + protected $locations = array( + 'module' => 'site/modules/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PuppetInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PuppetInstaller.php new file mode 100644 index 000000000..1a0a8a3fe --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PuppetInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/PxcmsInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/PxcmsInstaller.php new file mode 100644 index 000000000..fc58b8a6d --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/PxcmsInstaller.php @@ -0,0 +1,62 @@ + */ + protected $locations = array( + 'module' => 'app/Modules/{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Format package name. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'pxcms-module') { + return $this->inflectModuleVars($vars); + } + + if ($vars['type'] === 'pxcms-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * For package type pxcms-module, cut off a trailing '-plugin' if present. + * + * @param array $vars + * @return array + */ + protected function inflectModuleVars(array $vars): array + { + $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy) + $vars['name'] = str_replace('module-', '', $vars['name']); // strip out module- + $vars['name'] = $this->pregReplace('/-module$/', '', $vars['name']); // strip out -module + $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s + $vars['name'] = ucwords($vars['name']); // make module name camelcased + + return $vars; + } + + /** + * For package type pxcms-module, cut off a trailing '-plugin' if present. + * + * @param array $vars + * @return array + */ + protected function inflectThemeVars(array $vars): array + { + $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy) + $vars['name'] = str_replace('theme-', '', $vars['name']); // strip out theme- + $vars['name'] = $this->pregReplace('/-theme$/', '', $vars['name']); // strip out -theme + $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s + $vars['name'] = ucwords($vars['name']); // make module name camelcased + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/RadPHPInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/RadPHPInstaller.php new file mode 100644 index 000000000..4caae51d9 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/RadPHPInstaller.php @@ -0,0 +1,26 @@ + */ + protected $locations = array( + 'bundle' => 'src/{$name}/' + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $nameParts = explode('/', $vars['name']); + foreach ($nameParts as &$value) { + $value = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $value)); + $value = str_replace(array('-', '_'), ' ', $value); + $value = str_replace(' ', '', ucwords($value)); + } + $vars['name'] = implode('/', $nameParts); + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ReIndexInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ReIndexInstaller.php new file mode 100644 index 000000000..a19eaaf29 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ReIndexInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'theme' => 'themes/{$name}/', + 'plugin' => 'plugins/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/Redaxo5Installer.php b/kirki-composer/composer/installers/src/Composer/Installers/Redaxo5Installer.php new file mode 100644 index 000000000..b62c926a3 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/Redaxo5Installer.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'addon' => 'redaxo/src/addons/{$name}/', + 'bestyle-plugin' => 'redaxo/src/addons/be_style/plugins/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/RedaxoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/RedaxoInstaller.php new file mode 100644 index 000000000..26b3aa84a --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/RedaxoInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'addon' => 'redaxo/include/addons/{$name}/', + 'bestyle-plugin' => 'redaxo/include/addons/be_style/plugins/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/RoundcubeInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/RoundcubeInstaller.php new file mode 100644 index 000000000..7e7167485 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/RoundcubeInstaller.php @@ -0,0 +1,21 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + ); + + /** + * Lowercase name and changes the name to a underscores + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower(str_replace('-', '_', $vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/SMFInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/SMFInstaller.php new file mode 100644 index 000000000..7321046f1 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/SMFInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'module' => 'Sources/{$name}/', + 'theme' => 'Themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ShopwareInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ShopwareInstaller.php new file mode 100644 index 000000000..82b8e28c7 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ShopwareInstaller.php @@ -0,0 +1,66 @@ + */ + protected $locations = array( + 'backend-plugin' => 'engine/Shopware/Plugins/Local/Backend/{$name}/', + 'core-plugin' => 'engine/Shopware/Plugins/Local/Core/{$name}/', + 'frontend-plugin' => 'engine/Shopware/Plugins/Local/Frontend/{$name}/', + 'theme' => 'templates/{$name}/', + 'plugin' => 'custom/plugins/{$name}/', + 'frontend-theme' => 'themes/Frontend/{$name}/', + ); + + /** + * Transforms the names + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'shopware-theme') { + return $this->correctThemeName($vars); + } + + return $this->correctPluginName($vars); + } + + /** + * Changes the name to a camelcased combination of vendor and name + * + * @param array $vars + * @return array + */ + private function correctPluginName(array $vars): array + { + $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) { + return strtoupper($matches[0][1]); + }, $vars['name']); + + if (null === $camelCasedName) { + throw new \RuntimeException('Failed to run preg_replace_callback: '.preg_last_error()); + } + + $vars['name'] = ucfirst($vars['vendor']) . ucfirst($camelCasedName); + + return $vars; + } + + /** + * Changes the name to a underscore separated name + * + * @param array $vars + * @return array + */ + private function correctThemeName(array $vars): array + { + $vars['name'] = str_replace('-', '_', $vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/SilverStripeInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/SilverStripeInstaller.php new file mode 100644 index 000000000..aa2de2163 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/SilverStripeInstaller.php @@ -0,0 +1,33 @@ + */ + protected $locations = array( + 'module' => '{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Return the install path based on package type. + * + * Relies on built-in BaseInstaller behaviour with one exception: silverstripe/framework + * must be installed to 'sapphire' and not 'framework' if the version is <3.0.0 + */ + public function getInstallPath(PackageInterface $package, string $frameworkType = ''): string + { + if ( + $package->getName() == 'silverstripe/framework' + && preg_match('/^\d+\.\d+\.\d+/', $package->getVersion()) + && version_compare($package->getVersion(), '2.999.999') < 0 + ) { + return $this->templatePath($this->locations['module'], array('name' => 'sapphire')); + } + + return parent::getInstallPath($package, $frameworkType); + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/SiteDirectInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/SiteDirectInstaller.php new file mode 100644 index 000000000..0af3239b4 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/SiteDirectInstaller.php @@ -0,0 +1,34 @@ + */ + protected $locations = array( + 'module' => 'modules/{$vendor}/{$name}/', + 'plugin' => 'plugins/{$vendor}/{$name}/' + ); + + /** + * @param array $vars + * @return array + */ + public function inflectPackageVars(array $vars): array + { + return $this->parseVars($vars); + } + + /** + * @param array $vars + * @return array + */ + protected function parseVars(array $vars): array + { + $vars['vendor'] = strtolower($vars['vendor']) == 'sitedirect' ? 'SiteDirect' : $vars['vendor']; + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/StarbugInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/StarbugInstaller.php new file mode 100644 index 000000000..72afa081b --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/StarbugInstaller.php @@ -0,0 +1,14 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + 'theme' => 'themes/{$name}/', + 'custom-module' => 'app/modules/{$name}/', + 'custom-theme' => 'app/themes/{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/SyDESInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/SyDESInstaller.php new file mode 100644 index 000000000..24673d2f7 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/SyDESInstaller.php @@ -0,0 +1,55 @@ + */ + protected $locations = array( + 'module' => 'app/modules/{$name}/', + 'theme' => 'themes/{$name}/', + ); + + /** + * Format module name. + * + * Strip `sydes-` prefix and a trailing '-theme' or '-module' from package name if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] == 'sydes-module') { + return $this->inflectModuleVars($vars); + } + + if ($vars['type'] === 'sydes-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + public function inflectModuleVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/(^sydes-|-module$)/i', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectThemeVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/(^sydes-|-theme$)/', '', $vars['name']); + $vars['name'] = strtolower($vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/SyliusInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/SyliusInstaller.php new file mode 100644 index 000000000..c82bd8556 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/SyliusInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'theme' => 'themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/TaoInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/TaoInstaller.php new file mode 100644 index 000000000..8c1d81447 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/TaoInstaller.php @@ -0,0 +1,32 @@ + */ + protected $locations = array( + 'extension' => '{$name}' + ); + + public function inflectPackageVars(array $vars): array + { + $extra = $this->package->getExtra(); + + if (array_key_exists(self::EXTRA_TAO_EXTENSION_NAME, $extra)) { + $vars['name'] = $extra[self::EXTRA_TAO_EXTENSION_NAME]; + return $vars; + } + + $vars['name'] = str_replace('extension-', '', $vars['name']); + $vars['name'] = str_replace('-', ' ', $vars['name']); + $vars['name'] = lcfirst(str_replace(' ', '', ucwords($vars['name']))); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/TastyIgniterInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/TastyIgniterInstaller.php new file mode 100644 index 000000000..39ceae071 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/TastyIgniterInstaller.php @@ -0,0 +1,85 @@ + */ + protected $locations = [ + 'module' => 'app/{$name}/', + 'extension' => 'extensions/{$vendor}/{$name}/', + 'theme' => 'themes/{$name}/', + ]; + + /** + * Format package name. + * + * Cut off leading 'ti-ext-' or 'ti-theme-' if present. + * Strip vendor name of characters that is not alphanumeric or an underscore + * + */ + public function inflectPackageVars(array $vars): array + { + $extra = $this->package->getExtra(); + + if ($vars['type'] === 'tastyigniter-module') { + return $this->inflectModuleVars($vars); + } + + if ($vars['type'] === 'tastyigniter-extension') { + return $this->inflectExtensionVars($vars, $extra); + } + + if ($vars['type'] === 'tastyigniter-theme') { + return $this->inflectThemeVars($vars, $extra); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectModuleVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/^ti-module-/', '', $vars['name']); + + return $vars; + } + + /** + * @param array $vars + * @param array $extra + * @return array + */ + protected function inflectExtensionVars(array $vars, array $extra): array + { + if (!empty($extra['tastyigniter-extension']['code'])) { + $parts = explode('.', $extra['tastyigniter-extension']['code']); + $vars['vendor'] = (string)$parts[0]; + $vars['name'] = (string)($parts[1] ?? ''); + } + + $vars['vendor'] = $this->pregReplace('/[^a-z0-9_]/i', '', $vars['vendor']); + $vars['name'] = $this->pregReplace('/^ti-ext-/', '', $vars['name']); + + return $vars; + } + + /** + * @param array $vars + * @param array $extra + * @return array + */ + protected function inflectThemeVars(array $vars, array $extra): array + { + if (!empty($extra['tastyigniter-theme']['code'])) { + $vars['name'] = $extra['tastyigniter-theme']['code']; + } + + $vars['name'] = $this->pregReplace('/^ti-theme-/', '', $vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/TheliaInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/TheliaInstaller.php new file mode 100644 index 000000000..896bed5c0 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/TheliaInstaller.php @@ -0,0 +1,14 @@ + */ + protected $locations = array( + 'module' => 'local/modules/{$name}/', + 'frontoffice-template' => 'templates/frontOffice/{$name}/', + 'backoffice-template' => 'templates/backOffice/{$name}/', + 'email-template' => 'templates/email/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/TuskInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/TuskInstaller.php new file mode 100644 index 000000000..3b5f14249 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/TuskInstaller.php @@ -0,0 +1,17 @@ + + */ +class TuskInstaller extends BaseInstaller +{ + /** @var array */ + protected $locations = array( + 'task' => '.tusk/tasks/{$name}/', + 'command' => '.tusk/commands/{$name}/', + 'asset' => 'assets/tusk/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/UserFrostingInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/UserFrostingInstaller.php new file mode 100644 index 000000000..a646c5b2a --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/UserFrostingInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'sprinkle' => 'app/sprinkles/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/VanillaInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/VanillaInstaller.php new file mode 100644 index 000000000..06d5db3a4 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/VanillaInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'plugin' => 'plugins/{$name}/', + 'theme' => 'themes/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/VgmcpInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/VgmcpInstaller.php new file mode 100644 index 000000000..cf094dd59 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/VgmcpInstaller.php @@ -0,0 +1,59 @@ + */ + protected $locations = array( + 'bundle' => 'src/{$vendor}/{$name}/', + 'theme' => 'themes/{$name}/' + ); + + /** + * Format package name. + * + * For package type vgmcp-bundle, cut off a trailing '-bundle' if present. + * + * For package type vgmcp-theme, cut off a trailing '-theme' if present. + * + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'vgmcp-bundle') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'vgmcp-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectPluginVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-bundle$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectThemeVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/-theme$/', '', $vars['name']); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/WHMCSInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/WHMCSInstaller.php new file mode 100644 index 000000000..91b19fd03 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/WHMCSInstaller.php @@ -0,0 +1,22 @@ + */ + protected $locations = array( + 'addons' => 'modules/addons/{$vendor}_{$name}/', + 'fraud' => 'modules/fraud/{$vendor}_{$name}/', + 'gateways' => 'modules/gateways/{$vendor}_{$name}/', + 'notifications' => 'modules/notifications/{$vendor}_{$name}/', + 'registrars' => 'modules/registrars/{$vendor}_{$name}/', + 'reports' => 'modules/reports/{$vendor}_{$name}/', + 'security' => 'modules/security/{$vendor}_{$name}/', + 'servers' => 'modules/servers/{$vendor}_{$name}/', + 'social' => 'modules/social/{$vendor}_{$name}/', + 'support' => 'modules/support/{$vendor}_{$name}/', + 'templates' => 'templates/{$vendor}_{$name}/', + 'includes' => 'includes/{$vendor}_{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/WinterInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/WinterInstaller.php new file mode 100644 index 000000000..f75a6817c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/WinterInstaller.php @@ -0,0 +1,71 @@ + */ + protected $locations = array( + 'module' => 'modules/{$name}/', + 'plugin' => 'plugins/{$vendor}/{$name}/', + 'theme' => 'themes/{$name}/' + ); + + /** + * Format package name. + * + * For package type winter-plugin, cut off a trailing '-plugin' if present. + * + * For package type winter-theme, cut off a trailing '-theme' if present. + */ + public function inflectPackageVars(array $vars): array + { + if ($vars['type'] === 'winter-module') { + return $this->inflectModuleVars($vars); + } + + if ($vars['type'] === 'winter-plugin') { + return $this->inflectPluginVars($vars); + } + + if ($vars['type'] === 'winter-theme') { + return $this->inflectThemeVars($vars); + } + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectModuleVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/^wn-|-module$/', '', $vars['name']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectPluginVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/^wn-|-plugin$/', '', $vars['name']); + $vars['vendor'] = $this->pregReplace('/[^a-z0-9_]/i', '', $vars['vendor']); + + return $vars; + } + + /** + * @param array $vars + * @return array + */ + protected function inflectThemeVars(array $vars): array + { + $vars['name'] = $this->pregReplace('/^wn-|-theme$/', '', $vars['name']); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/WolfCMSInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/WolfCMSInstaller.php new file mode 100644 index 000000000..58a958791 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/WolfCMSInstaller.php @@ -0,0 +1,11 @@ + */ + protected $locations = array( + 'plugin' => 'wolf/plugins/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/WordPressInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/WordPressInstaller.php new file mode 100644 index 000000000..d46d5ab8e --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/WordPressInstaller.php @@ -0,0 +1,14 @@ + */ + protected $locations = array( + 'plugin' => 'wp-content/plugins/{$name}/', + 'theme' => 'wp-content/themes/{$name}/', + 'muplugin' => 'wp-content/mu-plugins/{$name}/', + 'dropin' => 'wp-content/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/YawikInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/YawikInstaller.php new file mode 100644 index 000000000..d609dea50 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/YawikInstaller.php @@ -0,0 +1,23 @@ + */ + protected $locations = array( + 'module' => 'module/{$name}/', + ); + + /** + * Format package name to CamelCase + */ + public function inflectPackageVars(array $vars): array + { + $vars['name'] = strtolower($this->pregReplace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); + $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); + $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); + + return $vars; + } +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ZendInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ZendInstaller.php new file mode 100644 index 000000000..ccfcd4a0c --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ZendInstaller.php @@ -0,0 +1,13 @@ + */ + protected $locations = array( + 'library' => 'library/{$name}/', + 'extra' => 'extras/library/{$name}/', + 'module' => 'module/{$name}/', + ); +} diff --git a/kirki-composer/composer/installers/src/Composer/Installers/ZikulaInstaller.php b/kirki-composer/composer/installers/src/Composer/Installers/ZikulaInstaller.php new file mode 100644 index 000000000..d1fd1d789 --- /dev/null +++ b/kirki-composer/composer/installers/src/Composer/Installers/ZikulaInstaller.php @@ -0,0 +1,12 @@ + */ + protected $locations = array( + 'module' => 'modules/{$vendor}-{$name}/', + 'theme' => 'themes/{$vendor}-{$name}/' + ); +} diff --git a/kirki-composer/composer/installers/src/bootstrap.php b/kirki-composer/composer/installers/src/bootstrap.php new file mode 100644 index 000000000..a5bb9add4 --- /dev/null +++ b/kirki-composer/composer/installers/src/bootstrap.php @@ -0,0 +1,18 @@ + **ℹ️ Please Note:** [Composer treats _minor_ releases below 1.0.0 as _major_ releases][composer-manual-caret]. So version `0.7.x` (or higher) of this plugin must be _explicitly_ set as version constraint when using Composer 2.x or PHP 8.0. In other words: using `^0.6` will **not** work with Composer 2.x or PHP 8.0. + +### How it works + +Basically, this plugin executes the following steps: + +- This plugin searches for [`phpcodesniffer-standard` packages][] in all of your currently installed Composer packages. +- Matching packages and the project itself are scanned for PHP_CodeSniffer rulesets. +- The plugin will call PHP_CodeSniffer and configure the `installed_paths` option. + +### Example project + +The following is an example Composer project and has included +multiple `phpcodesniffer-standard` packages. + +```json +{ + "name": "example/project", + "description": "Just an example project", + "type": "project", + "require": {}, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "*", + "object-calisthenics/phpcs-calisthenics-rules": "*", + "phpcompatibility/php-compatibility": "*", + "wp-coding-standards/wpcs": "*" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} +``` + +After running `composer install` PHP_CodeSniffer just works: + +```bash +$ ./vendor/bin/phpcs -i +The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, ObjectCalisthenics, +PHPCompatibility, WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra +``` + +### Calling the plugin directly + +In some circumstances, it is desirable to call this plugin's functionality +directly. For instance, during development or in [CI][definition-ci] environments. + +As the plugin requires Composer to work, direct calls need to be wired through a +project's `composer.json`. + +This is done by adding a call to the `Plugin::run` function in the `script` +section of the `composer.json`: + +```json +{ + "scripts": { + "install-codestandards": [ + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ] + } +} +``` + +The command can then be called using `composer run-script install-codestandards` or +referenced from other script configurations, as follows: + +```json +{ + "scripts": { + "install-codestandards": [ + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ], + "post-install-cmd": [ + "@install-codestandards" + ] + } +} +``` + +For more details about Composer scripts, please refer to [the section on scripts +in the Composer manual][composer-manual-scripts]. + +### Changing the Coding Standards search depth + +By default, this plugin searches up for Coding Standards up to three directories +deep. In most cases, this should be sufficient. However, this plugin allows +you to customize the search depth setting if needed. + +```json +{ + "extra": { + "phpcodesniffer-search-depth": 5 + } +} +``` + +### Caveats + +When this plugin is installed globally, composer will load the _global_ plugin rather +than the one from the local repository. Despite [this behavior being documented +in the composer manual][using-composer-plugins], it could potentially confuse +as another version of the plugin could be run and not the one specified by the project. + +## Developing Coding Standards + +Coding standard can be developed normally, as documented by [PHP_CodeSniffer][codesniffer], in the [Coding Standard Tutorial][tutorial]. + +Create a composer package of your coding standard by adding a `composer.json` file. + +```json +{ + "name" : "acme/phpcodesniffer-our-standards", + "description" : "Package contains all coding standards of the Acme company", + "require" : { + "php" : ">=5.4.0", + "squizlabs/php_codesniffer" : "^3.6" + }, + "type" : "phpcodesniffer-standard" +} +``` + +Requirements: +* The repository may contain one or more standards. +* Each standard can have a separate directory no deeper than 3 levels from the repository root. +* The package `type` must be `phpcodesniffer-standard`. Without this, the plugin will not trigger. + +### Requiring the plugin from within your coding standard + +If your coding standard itself depends on additional external PHPCS standards, this plugin can +make life easier on your end-users by taking care of the installation of all standards - yours +and your dependencies - for them. + +This can help reduce the number of support questions about setting the `installed_paths`, as well +as simplify your standard's installation instructions. + +For this to work, make sure your external standard adds this plugin to the `composer.json` config +via `require`, **not** `require-dev`. + +> :warning: Your end-user may already `require-dev` this plugin and/or other external standards used +> by your end-users may require this plugin as well. +> +> To prevent your end-users getting into "_dependency hell_", make sure to make the version requirement +> for this plugin flexible. +> +> As, for now, this plugin is still regarded as "unstable" (version < 1.0), remember that Composer +> treats unstable minors as majors and will not be able to resolve one config requiring this plugin +> at version `^0.5`, while another requires it at version `^0.6`. +> Either allow multiple minors or use `*` as the version requirement. +> +> Some examples of flexible requirements which can be used: +> ```bash +> composer require dealerdirect/phpcodesniffer-composer-installer:"*" +> composer require dealerdirect/phpcodesniffer-composer-installer:"0.*" +> composer require dealerdirect/phpcodesniffer-composer-installer:"^0.4.1 || ^0.5 || ^0.6 || ^0.7" +> ``` + +## Changelog + +This repository does not contain a `CHANGELOG.md` file, however, we do publish a changelog on each release +using the [GitHub releases][changelog] functionality. + +## Contributing + +This is an active open-source project. We are always open to people who want to +use the code or contribute to it. + +We've set up a separate document for our [contribution guidelines][contributing-guidelines]. + +Thank you for being involved! :heart_eyes: + +## Authors & contributors + +The original idea and setup of this repository is by [Franck Nijhof][frenck], employee @ Dealerdirect. + +For a full list of all author and/or contributors, check [the contributors page][contributors]. + +## License + +The MIT License (MIT) + +Copyright (c) 2016-2022 Dealerdirect B.V. and contributors +Copyright (c) 2022 PHPCSStandards and contributors + +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. + +[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg +[changelog]: https://github.com/PHPCSStandards/composer-installer/releases +[code-of-conduct-shield]: https://img.shields.io/badge/Contributor%20Covenant-v2.0-ff69b4.svg +[code-of-conduct]: CODE_OF_CONDUCT.md +[codesniffer]: https://github.com/squizlabs/PHP_CodeSniffer +[composer-manual-scripts]: https://getcomposer.org/doc/articles/scripts.md +[composer-manual-caret]: https://getcomposer.org/doc/articles/versions.md#caret-version-range- +[composer]: https://getcomposer.org/ +[contributing-guidelines]: CONTRIBUTING.md +[contributors]: https://github.com/PHPCSStandards/composer-installer/graphs/contributors +[definition-ci]: https://en.wikipedia.org/wiki/Continuous_integration +[frenck]: https://github.com/frenck +[last-updated-shield]: https://img.shields.io/github/last-commit/PHPCSStandards/composer-installer.svg +[license-shield]: https://img.shields.io/github/license/PHPCSStandards/composer-installer.svg +[packagist-shield]: https://img.shields.io/packagist/dt/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-version-shield]: https://img.shields.io/packagist/v/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-version]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer +[packagist]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer +[`phpcodesniffer-standard` packages]: https://packagist.org/explore/?type=phpcodesniffer-standard +[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg +[scrutinizer-shield]: https://img.shields.io/scrutinizer/g/dealerdirect/phpcodesniffer-composer-installer.svg +[scrutinizer]: https://scrutinizer-ci.com/g/dealerdirect/phpcodesniffer-composer-installer/ +[ghactionstest-shield]: https://github.com/PHPCSStandards/composer-installer/actions/workflows/integrationtest.yml/badge.svg +[ghactions]: https://github.com/PHPCSStandards/composer-installer/actions/workflows/integrationtest.yml +[tutorial]: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial +[using-composer-plugins]: https://getcomposer.org/doc/articles/plugins.md#using-plugins +[v0.4]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v0.4.0 +[v0.7]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v0.7.0 diff --git a/kirki-composer/dealerdirect/phpcodesniffer-composer-installer/composer.json b/kirki-composer/dealerdirect/phpcodesniffer-composer-installer/composer.json new file mode 100644 index 000000000..bf3355ac4 --- /dev/null +++ b/kirki-composer/dealerdirect/phpcodesniffer-composer-installer/composer.json @@ -0,0 +1,71 @@ +{ + "name": "dealerdirect/phpcodesniffer-composer-installer", + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "type": "composer-plugin", + "keywords": [ + "composer", "installer", "plugin", + "phpcs", "phpcbf", "codesniffer", "phpcodesniffer", "php_codesniffer", + "standard", "standards", "style guide", "stylecheck", + "qa", "quality", "code quality", "tests" + ], + "homepage": "http://www.dealerdirect.com", + "license": "MIT", + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name" : "Contributors", + "homepage" : "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "require": { + "php": ">=5.4", + "composer-plugin-api": "^1.0 || ^2.0", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "ext-json": "*", + "ext-zip": "*", + "composer/composer": "*", + "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "yoast/phpunit-polyfills": "^1.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Tests\\": "tests/" + } + }, + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "scripts": { + "install-codestandards": [ + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ], + "lint": [ + "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --exclude vendor --exclude .git" + ], + "test": [ + "@php ./vendor/phpunit/phpunit/phpunit --no-coverage" + ], + "coverage": [ + "@php ./vendor/phpunit/phpunit/phpunit" + ] + } +} diff --git a/kirki-composer/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php b/kirki-composer/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php new file mode 100644 index 000000000..a2863d6c8 --- /dev/null +++ b/kirki-composer/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php @@ -0,0 +1,637 @@ + + */ +class Plugin implements PluginInterface, EventSubscriberInterface +{ + const KEY_MAX_DEPTH = 'phpcodesniffer-search-depth'; + + const MESSAGE_ERROR_WRONG_MAX_DEPTH = + 'The value of "%s" (in the composer.json "extra".section) must be an integer larger than %d, %s given.'; + + const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed'; + const MESSAGE_NOTHING_TO_INSTALL = 'No PHPCS standards to install or update'; + const MESSAGE_PLUGIN_UNINSTALLED = 'PHPCodeSniffer Composer Installer is uninstalled'; + const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer'; + + const PACKAGE_NAME = 'squizlabs/php_codesniffer'; + const PACKAGE_TYPE = 'phpcodesniffer-standard'; + + const PHPCS_CONFIG_REGEX = '`%s:[^\r\n]+`'; + const PHPCS_CONFIG_KEY = 'installed_paths'; + + const PLUGIN_NAME = 'dealerdirect/phpcodesniffer-composer-installer'; + + /** + * @var Composer + */ + private $composer; + + /** + * @var string + */ + private $cwd; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var array + */ + private $installedPaths; + + /** + * @var IOInterface + */ + private $io; + + /** + * @var ProcessExecutor + */ + private $processExecutor; + + /** + * Triggers the plugin's main functionality. + * + * Makes it possible to run the plugin as a custom command. + * + * @param Event $event + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public static function run(Event $event) + { + $io = $event->getIO(); + $composer = $event->getComposer(); + + $instance = new static(); + + $instance->io = $io; + $instance->composer = $composer; + $instance->init(); + $instance->onDependenciesChangedEvent(); + } + + /** + * {@inheritDoc} + * + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public function activate(Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->io = $io; + + $this->init(); + } + + /** + * {@inheritDoc} + */ + public function deactivate(Composer $composer, IOInterface $io) + { + } + + /** + * {@inheritDoc} + */ + public function uninstall(Composer $composer, IOInterface $io) + { + } + + /** + * Prepares the plugin so it's main functionality can be run. + * + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + private function init() + { + $this->cwd = getcwd(); + $this->installedPaths = array(); + + $this->processExecutor = new ProcessExecutor($this->io); + $this->filesystem = new Filesystem($this->processExecutor); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + ScriptEvents::POST_INSTALL_CMD => array( + array('onDependenciesChangedEvent', 0), + ), + ScriptEvents::POST_UPDATE_CMD => array( + array('onDependenciesChangedEvent', 0), + ), + ); + } + + /** + * Entry point for post install and post update events. + * + * @throws \InvalidArgumentException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public function onDependenciesChangedEvent() + { + $io = $this->io; + $isVerbose = $io->isVerbose(); + $exitCode = 0; + + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_RUNNING_INSTALLER)); + } + + if ($this->isPHPCodeSnifferInstalled() === true) { + $this->loadInstalledPaths(); + $installPathCleaned = $this->cleanInstalledPaths(); + $installPathUpdated = $this->updateInstalledPaths(); + + if ($installPathCleaned === true || $installPathUpdated === true) { + $exitCode = $this->saveInstalledPaths(); + } elseif ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_NOTHING_TO_INSTALL)); + } + } else { + $pluginPackage = $this + ->composer + ->getRepositoryManager() + ->getLocalRepository() + ->findPackages(self::PLUGIN_NAME) + ; + + $isPluginUninstalled = count($pluginPackage) === 0; + + if ($isPluginUninstalled) { + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_PLUGIN_UNINSTALLED)); + } + } else { + $exitCode = 1; + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_NOT_INSTALLED)); + } + } + } + + return $exitCode; + } + + /** + * Load all paths from PHP_CodeSniffer into an array. + * + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + private function loadInstalledPaths() + { + if ($this->isPHPCodeSnifferInstalled() === true) { + $this->processExecutor->execute( + $this->getPhpcsCommand() . ' --config-show', + $output, + $this->getPHPCodeSnifferInstallPath() + ); + + $regex = sprintf(self::PHPCS_CONFIG_REGEX, self::PHPCS_CONFIG_KEY); + if (preg_match($regex, $output, $match) === 1) { + $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $match[0]); + $phpcsInstalledPaths = trim($phpcsInstalledPaths); + + if ($phpcsInstalledPaths !== '') { + $this->installedPaths = explode(',', $phpcsInstalledPaths); + } + } + } + } + + /** + * Save all coding standard paths back into PHP_CodeSniffer + * + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + * + * @return int Exit code. 0 for success, 1 or higher for failure. + */ + private function saveInstalledPaths() + { + // Check if we found installed paths to set. + if (count($this->installedPaths) !== 0) { + sort($this->installedPaths); + $paths = implode(',', $this->installedPaths); + $arguments = array('--config-set', self::PHPCS_CONFIG_KEY, $paths); + $configMessage = sprintf( + 'PHP CodeSniffer Config %s set to %s', + self::PHPCS_CONFIG_KEY, + $paths + ); + } else { + // Delete the installed paths if none were found. + $arguments = array('--config-delete', self::PHPCS_CONFIG_KEY); + $configMessage = sprintf( + 'PHP CodeSniffer Config %s delete', + self::PHPCS_CONFIG_KEY + ); + } + + // Prepare message in case of failure + $failMessage = sprintf( + 'Failed to set PHP CodeSniffer %s Config', + self::PHPCS_CONFIG_KEY + ); + + // Okay, lets rock! + $command = vsprintf( + '%s %s', + array( + 'phpcs command' => $this->getPhpcsCommand(), + 'arguments' => implode(' ', $arguments), + ) + ); + + $exitCode = $this->processExecutor->execute($command, $configResult, $this->getPHPCodeSnifferInstallPath()); + if ($exitCode === 0) { + $exitCode = $this->verifySaveSuccess(); + } + + if ($exitCode === 0) { + $this->io->write($configMessage); + } else { + $this->io->write($failMessage); + } + + if ($this->io->isVerbose() && !empty($configResult)) { + $this->io->write(sprintf('%s', $configResult)); + } + + return $exitCode; + } + + /** + * Verify that the paths which were expected to be saved, have been. + * + * @return int Exit code. 0 for success, 1 for failure. + */ + private function verifySaveSuccess() + { + $exitCode = 1; + $expectedPaths = $this->installedPaths; + + // Request the currently set installed paths after the save. + $this->loadInstalledPaths(); + + $registeredPaths = array_intersect($this->installedPaths, $expectedPaths); + $registeredCount = count($registeredPaths); + $expectedCount = count($expectedPaths); + + if ($expectedCount === $registeredCount) { + $exitCode = 0; + } + + if ($exitCode === 1 && $this->io->isVerbose()) { + $verificationMessage = sprintf( + "Paths to external standards found by the plugin: %s\n" + . 'Actual paths registered with PHPCS: %s', + implode(', ', $expectedPaths), + implode(', ', $this->installedPaths) + ); + $this->io->write($verificationMessage); + } + + return $exitCode; + } + + /** + * Get the command to call PHPCS. + */ + protected function getPhpcsCommand() + { + // Determine the path to the main PHPCS file. + $phpcsPath = $this->getPHPCodeSnifferInstallPath(); + if (file_exists($phpcsPath . '/bin/phpcs') === true) { + // PHPCS 3.x. + $phpcsExecutable = './bin/phpcs'; + } else { + // PHPCS 2.x. + $phpcsExecutable = './scripts/phpcs'; + } + + return vsprintf( + '%s %s', + array( + 'php executable' => $this->getPhpExecCommand(), + 'phpcs executable' => $phpcsExecutable, + ) + ); + } + + /** + * Get the path to the current PHP version being used. + * + * Duplicate of the same in the EventDispatcher class in Composer itself. + */ + protected function getPhpExecCommand() + { + $finder = new PhpExecutableFinder(); + + $phpPath = $finder->find(false); + + if ($phpPath === false) { + throw new \RuntimeException('Failed to locate PHP binary to execute ' . $phpPath); + } + + $phpArgs = $finder->findArguments(); + $phpArgs = $phpArgs + ? ' ' . implode(' ', $phpArgs) + : '' + ; + + $command = ProcessExecutor::escape($phpPath) . + $phpArgs . + ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen')) . + ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions')) . + ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit')) + ; + + return $command; + } + + /** + * Iterate trough all known paths and check if they are still valid. + * + * If path does not exists, is not an directory or isn't readable, the path + * is removed from the list. + * + * @return bool True if changes where made, false otherwise + */ + private function cleanInstalledPaths() + { + $changes = false; + foreach ($this->installedPaths as $key => $path) { + // This might be a relative path as well + $alternativePath = realpath($this->getPHPCodeSnifferInstallPath() . \DIRECTORY_SEPARATOR . $path); + + if ( + (is_dir($path) === false || is_readable($path) === false) && + ( + $alternativePath === false || + is_dir($alternativePath) === false || + is_readable($alternativePath) === false + ) + ) { + unset($this->installedPaths[$key]); + $changes = true; + } + } + return $changes; + } + + /** + * Check all installed packages (including the root package) against + * the installed paths from PHP_CodeSniffer and add the missing ones. + * + * @return bool True if changes where made, false otherwise + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + private function updateInstalledPaths() + { + $changes = false; + $searchPaths = array(); + + // Add root package only if it has the expected package type. + if ( + $this->composer->getPackage() instanceof RootPackageInterface + && $this->composer->getPackage()->getType() === self::PACKAGE_TYPE + ) { + $searchPaths[] = $this->cwd; + } + + $codingStandardPackages = $this->getPHPCodingStandardPackages(); + foreach ($codingStandardPackages as $package) { + $installPath = $this->composer->getInstallationManager()->getInstallPath($package); + if ($this->filesystem->isAbsolutePath($installPath) === false) { + $installPath = $this->filesystem->normalizePath( + $this->cwd . \DIRECTORY_SEPARATOR . $installPath + ); + } + $searchPaths[] = $installPath; + } + + // Nothing to do. + if ($searchPaths === array()) { + return false; + } + + $finder = new Finder(); + $finder->files() + ->depth('<= ' . $this->getMaxDepth()) + ->depth('>= ' . $this->getMinDepth()) + ->ignoreUnreadableDirs() + ->ignoreVCS(true) + ->in($searchPaths) + ->name('ruleset.xml'); + + // Process each found possible ruleset. + foreach ($finder as $ruleset) { + $standardsPath = $ruleset->getPath(); + + // Pick the directory above the directory containing the standard, unless this is the project root. + if ($standardsPath !== $this->cwd) { + $standardsPath = dirname($standardsPath); + } + + // Use relative paths for local project repositories. + if ($this->isRunningGlobally() === false) { + $standardsPath = $this->filesystem->findShortestPath( + $this->getPHPCodeSnifferInstallPath(), + $standardsPath, + true + ); + } + + // De-duplicate and add when directory is not configured. + if (in_array($standardsPath, $this->installedPaths, true) === false) { + $this->installedPaths[] = $standardsPath; + $changes = true; + } + } + + return $changes; + } + + /** + * Iterates through Composers' local repository looking for valid Coding + * Standard packages. + * + * @return array Composer packages containing coding standard(s) + */ + private function getPHPCodingStandardPackages() + { + $codingStandardPackages = array_filter( + $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(), + function (PackageInterface $package) { + if ($package instanceof AliasPackage) { + return false; + } + return $package->getType() === Plugin::PACKAGE_TYPE; + } + ); + + return $codingStandardPackages; + } + + /** + * Searches for the installed PHP_CodeSniffer Composer package + * + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against + * + * @return PackageInterface|null + */ + private function getPHPCodeSnifferPackage($versionConstraint = null) + { + $packages = $this + ->composer + ->getRepositoryManager() + ->getLocalRepository() + ->findPackages(self::PACKAGE_NAME, $versionConstraint); + + return array_shift($packages); + } + + /** + * Returns the path to the PHP_CodeSniffer package installation location + * + * @return string + */ + private function getPHPCodeSnifferInstallPath() + { + return $this->composer->getInstallationManager()->getInstallPath($this->getPHPCodeSnifferPackage()); + } + + /** + * Simple check if PHP_CodeSniffer is installed. + * + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against + * + * @return bool Whether PHP_CodeSniffer is installed + */ + private function isPHPCodeSnifferInstalled($versionConstraint = null) + { + return ($this->getPHPCodeSnifferPackage($versionConstraint) !== null); + } + + /** + * Test if composer is running "global" + * This check kinda dirty, but it is the "Composer Way" + * + * @return bool Whether Composer is running "globally" + * + * @throws \RuntimeException + */ + private function isRunningGlobally() + { + return ($this->composer->getConfig()->get('home') === $this->cwd); + } + + /** + * Determines the maximum search depth when searching for Coding Standards. + * + * @return int + * + * @throws \InvalidArgumentException + */ + private function getMaxDepth() + { + $maxDepth = 3; + + $extra = $this->composer->getPackage()->getExtra(); + + if (array_key_exists(self::KEY_MAX_DEPTH, $extra)) { + $maxDepth = $extra[self::KEY_MAX_DEPTH]; + $minDepth = $this->getMinDepth(); + + if ( + (string) (int) $maxDepth !== (string) $maxDepth /* Must be an integer or cleanly castable to one */ + || $maxDepth <= $minDepth /* Larger than the minimum */ + || is_float($maxDepth) === true /* Within the boundaries of integer */ + ) { + $message = vsprintf( + self::MESSAGE_ERROR_WRONG_MAX_DEPTH, + array( + 'key' => self::KEY_MAX_DEPTH, + 'min' => $minDepth, + 'given' => var_export($maxDepth, true), + ) + ); + + throw new \InvalidArgumentException($message); + } + } + + return (int) $maxDepth; + } + + /** + * Returns the minimal search depth for Coding Standard packages. + * + * Usually this is 0, unless PHP_CodeSniffer >= 3 is used. + * + * @return int + */ + private function getMinDepth() + { + if ($this->isPHPCodeSnifferInstalled('>= 3.0.0') !== true) { + return 1; + } + return 0; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/CHANGELOG.md b/kirki-composer/phpcompatibility/php-compatibility/CHANGELOG.md new file mode 100644 index 000000000..b92ae2540 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/CHANGELOG.md @@ -0,0 +1,1488 @@ +# Change Log for the PHPCompatibility standard for PHP Codesniffer + +All notable changes to this project will be documented in this file. + +This projects adheres to [Keep a CHANGELOG](http://keepachangelog.com/). + +Up to version 8.0.0, the `major.minor` version numbers were based on the PHP version for which compatibility check support was added, with `patch` version numbers being specific to this library. +From version 8.0.0 onwards, [Semantic Versioning](http://semver.org/) is used. + + + + +## [Unreleased] + +_Nothing yet._ + +## [9.3.5] - 2019-12-27 + +See all related issues and PRs in the [9.3.5 milestone]. + +### Added +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `FFI` extension related classes as introduced in PHP 7.4. [#949](https://github.com/PHPCompatibility/PHPCompatibility/pull/949) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: detect use of the new `FFI` extension related ini directives as introduced in PHP 7.4. [#949](https://github.com/PHPCompatibility/PHPCompatibility/pull/949) + +### Changed +- :pencil: `PHPCompatibility.Syntax.NewShortArray`: improved clarity of the error message and made it consistent with other error messages in this standard. [#934](https://github.com/PHPCompatibility/PHPCompatibility/pull/934) +- :pencil: `PHPCompatibility.Interfaces.NewInterfaces`: updated the URL which is mentioned in select error messages. [#942](https://github.com/PHPCompatibility/PHPCompatibility/pull/942) +- :recycle: Another slew of code documentation fixes. [#937](https://github.com/PHPCompatibility/PHPCompatibility/pull/937), [#939](https://github.com/PHPCompatibility/PHPCompatibility/pull/939), [#940](https://github.com/PHPCompatibility/PHPCompatibility/pull/940), [#941](https://github.com/PHPCompatibility/PHPCompatibility/pull/941), [#943](https://github.com/PHPCompatibility/PHPCompatibility/pull/943), [#944](https://github.com/PHPCompatibility/PHPCompatibility/pull/944), [#951](https://github.com/PHPCompatibility/PHPCompatibility/pull/951), [#950](https://github.com/PHPCompatibility/PHPCompatibility/pull/950). Fixes [#734](https://github.com/PHPCompatibility/PHPCompatibility/issues/734). +- :green_heart: Travis: various tweaks. The builds against PHP 7.4 are no longer allowed to fail. [#935](https://github.com/PHPCompatibility/PHPCompatibility/pull/935), [#938](https://github.com/PHPCompatibility/PHPCompatibility/pull/938) + For running the sniffs on PHP 7.4, it is recommended to use PHP_CodeSniffer 3.5.0+ as PHP_CodeSniffer itself is + not compatible with PHP 7.4 until version 3.5.0. + +### Fixed +- :bug: `PHPCompatibility.Classes.NewClasses`: two new PHP 7.4 classes were being checked as if they were Exceptions. [#945](https://github.com/PHPCompatibility/PHPCompatibility/pull/945) + +### Credits +Thanks go out to [William Entriken] for their contribution to this version. :clap: + + +## [9.3.4] - 2019-11-15 + +See all related issues and PRs in the [9.3.4 milestone]. + +### Fixed +- :bug: `PHPCompatibility.Keywords.ForbiddenNames`: false positive for list when used in a `foreach()` condition. [#930](https://github.com/PHPCompatibility/PHPCompatibility/pull/930). Fixes [#928](https://github.com/PHPCompatibility/PHPCompatibility/issues/928), [#929](https://github.com/PHPCompatibility/PHPCompatibility/pull/929) + +### Credits +Thanks go out to [Sergii Bondarenko] for their contribution to this version. :clap: + + +## [9.3.3] - 2019-11-11 + +See all related issues and PRs in the [9.3.3 milestone]. + +### Added +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of yet more (undocumented) PHP 7.2 Sodium constants. [#924](https://github.com/PHPCompatibility/PHPCompatibility/pull/924) +- :star: `PHPCompatibility.Keywords.ForbiddenNames` sniff: detect the use of more reserved keywords which are not allowed to be used to name certain constructs. [#923](https://github.com/PHPCompatibility/PHPCompatibility/pull/923). Fixes [#922](https://github.com/PHPCompatibility/PHPCompatibility/issues/922) + +### Fixed +- :bug: `PHPCompatibility.FunctionNameRestrictions.RemovedPHP4StyleConstructors`: false positive detecting PHP4-style constructors when declared in interfaces. The class implementing the interface will not have the same name as the interface, so the actual method would not be regarded as a PHP4 style constructor. [#921](https://github.com/PHPCompatibility/PHPCompatibility/pull/921) + +### Credits +Thanks go out to [Nikhil] for their contribution to this version. :clap: + + +## [9.3.2] - 2019-10-16 + +See all related issues and PRs in the [9.3.2 milestone]. + +### Added +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the PHP 7.2 `SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13` constant. [#915](https://github.com/PHPCompatibility/PHPCompatibility/pull/915) +- :books: Readme: a list of projects which are build upon or extend PHPCompatibility. [#904](https://github.com/PHPCompatibility/PHPCompatibility/pull/904) + +### Changed +- :pushpin: `PHPCompatibility.FunctionNameRestrictions.RemovedPHP4StyleConstructors`: minor efficiency fix to make the sniff faster. [#912](https://github.com/PHPCompatibility/PHPCompatibility/pull/912) +- :pushpin: `PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames`: functions marked as `@deprecated` in the function docblock will now be ignored by this sniff. [#917](https://github.com/PHPCompatibility/PHPCompatibility/pull/917). Fixes [#911](https://github.com/PHPCompatibility/PHPCompatibility/issues/911) +- :pencil: `PHPCompatibility.FunctionDeclarations.ForbiddenToStringParameters`: the `$ooScopeTokens` property is now `protected`, it should never have been `public` in the first place. [#907](https://github.com/PHPCompatibility/PHPCompatibility/pull/907) +- :recycle: More code documentation fixes. [#903](https://github.com/PHPCompatibility/PHPCompatibility/pull/903), [#916](https://github.com/PHPCompatibility/PHPCompatibility/pull/916) +- :books: Readme/Contributing: various tweaks. [#904](https://github.com/PHPCompatibility/PHPCompatibility/pull/904), [#905](https://github.com/PHPCompatibility/PHPCompatibility/pull/905) + +### Fixed +- :bug: `PHPCompatibility.FunctionUse.OptionalToRequiredFunctionParameters`: false positive when a class is instantiated which has the same name as one of the affected functions. [#914](https://github.com/PHPCompatibility/PHPCompatibility/pull/914). Fixes [#913](https://github.com/PHPCompatibility/PHPCompatibility/issues/913) +- :bug: `PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters`: false positive when a class is instantiated which has the same name as one of the affected functions. [#914](https://github.com/PHPCompatibility/PHPCompatibility/pull/914) +- :bug: `PHPCompatibility.MethodUse.NewDirectCallsToClone`: false positive on calling `__clone()` from within the class being cloned [#910](https://github.com/PHPCompatibility/PHPCompatibility/pull/910). Fixes [#629 (comment)](https://github.com/PHPCompatibility/PHPCompatibility/issues/629#issuecomment-532607809) +- :bug: `PHPCompatibility.Miscellaneous.ValidIntegers`: binary numbers using an uppercase `B` were not always recognized correctly. [#909](https://github.com/PHPCompatibility/PHPCompatibility/pull/909) + + +## [9.3.1] - 2019-09-06 + +See all related issues and PRs in the [9.3.1 milestone]. + +### Changed +- :recycle: A whole slew of code documentation fixes. [#892](https://github.com/PHPCompatibility/PHPCompatibility/pull/892), [#895](https://github.com/PHPCompatibility/PHPCompatibility/pull/895), [#896](https://github.com/PHPCompatibility/PHPCompatibility/pull/896), [#897](https://github.com/PHPCompatibility/PHPCompatibility/pull/897), [#898](https://github.com/PHPCompatibility/PHPCompatibility/pull/898), [#899](https://github.com/PHPCompatibility/PHPCompatibility/pull/899), [#900](https://github.com/PHPCompatibility/PHPCompatibility/pull/900) +- :wrench: Travis: minor tweaks to the build script. [#893](https://github.com/PHPCompatibility/PHPCompatibility/pull/893) + +### Fixed +- :bug: `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder`: false positive when an array item in the second parameter contained a ternary. [#891](https://github.com/PHPCompatibility/PHPCompatibility/pull/891). Fixes [#890](https://github.com/PHPCompatibility/PHPCompatibility/issues/890) +- :bug: `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder`: will now take array casts into account when determining which parameter is `$pieces`. [#891](https://github.com/PHPCompatibility/PHPCompatibility/pull/891). +- :bug: `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder`: hardening of the logic to not examine the second parameter when the first is just and only a text string (`$glue`). [#891](https://github.com/PHPCompatibility/PHPCompatibility/pull/891). + + +## [9.3.0] - 2019-08-29 + +See all related issues and PRs in the [9.3.0 milestone]. + +To keep informed of the progress of covering "_everything PHP 7.4_" in PHPCompatibility, please subscribe to issue [#808](https://github.com/PHPCompatibility/PHPCompatibility/issues/808). + +### Changes expected in PHPCompatibility 10.0.0 +The next version of PHPCompatibility is expected to include a new external dependency. + +In this same release, support for PHP < 5.4 and PHP_CodeSniffer < 2.6.0 will be dropped. + +The `10.0.0` release is expected around the same time as the release of PHP 7.4 - end of November/beginning of December 2019. + +### Added +- :star2: New `PHPCompatibility.Miscellaneous.NewPHPOpenTagEOF` sniff to detect a stand-alone PHP open tag at the end of a file, without trailing newline, as will be supported as of PHP 7.4. [#843](https://github.com/PHPCompatibility/PHPCompatibility/pull/846) +- :star2: New `PHPCompatibility.ParameterValues.ForbiddenStripTagsSelfClosingXHTML` sniff to detect calls to `strip_tags()` passing self-closing XHTML tags in the `$allowable_tags` parameter. This has not been supported since PHP 5.3.4. [#866](https://github.com/PHPCompatibility/PHPCompatibility/pull/866) +- :star2: New `PHPCompatibility.ParameterValues.NewHTMLEntitiesEncodingDefault` sniff to detect calls to `html_entity_decode()`, `htmlentities()` and `htmlspecialchars()` which are impacted by the change to the default value of the `$encoding` parameter in PHP 5.4. [#862](https://github.com/PHPCompatibility/PHPCompatibility/pull/862) +- :star2: New `PHPCompatibility.ParameterValues.NewIconvMbstringCharsetDefault` sniff to detect code impacted by the change in the `default_charset` value in PHP 5.6. [#864](https://github.com/PHPCompatibility/PHPCompatibility/pull/864) Fixes [#839](https://github.com/PHPCompatibility/PHPCompatibility/issues/839) +- :star2: New `PHPCompatibility.ParameterValues.NewIDNVariantDefault` sniff to detect calls to `idn_to_ascii()` and `idn_to_utf8()` impacted by the PHP 7.4 change in the default value for the `$variant` parameter. [#861](https://github.com/PHPCompatibility/PHPCompatibility/pull/861) +- :star2: New `PHPCompatibility.ParameterValues.NewPasswordAlgoConstantValues` sniff to detect calls to `password_hash()` and `password_needs_rehash()` impacted by the changed value of the `PASSWORD_DEFAULT`, `PASSWORD_BCRYPT`, `PASSWORD_ARGON2I` and `PASSWORD_ARGON2ID` constants in PHP 7.4. [#865](https://github.com/PHPCompatibility/PHPCompatibility/pull/865) +- :star2: New `PHPCompatibility.ParameterValues.NewProcOpenCmdArray` sniff to detect calls to `proc_open()` passing an array for the `$cmd` parameter as supported as of PHP 7.4. [#869](https://github.com/PHPCompatibility/PHPCompatibility/pull/869) +- :star2: New `PHPCompatibility.ParameterValues.NewStripTagsAllowableTagsArray` sniff to detect calls to `strip_tags()` passing an array for the `$allowable_tags` parameter as will be supported as of PHP 7.4. [#867](https://github.com/PHPCompatibility/PHPCompatibility/pull/867) +- :star2: New `PHPCompatibility.ParameterValues.RemovedImplodeFlexibleParamOrder` sniff to detect `implode()` being called with `$glue` and `$pieces` in reverse order from the documented argument order. This was previously allowed for historical reasons, but will be deprecated in PHP 7.4. [#846](https://github.com/PHPCompatibility/PHPCompatibility/pull/846) +- :star2: New `PHPCompatibility.ParameterValues.RemovedMbStrrposEncodingThirdParam` sniff to detect the `$encoding` being passed as the third, instead of the fourth parameter, to `mb_strrpos()` as has been soft deprecated since PHP 5.2 and will be hard deprecated as of PHP 7.4. [#860](https://github.com/PHPCompatibility/PHPCompatibility/pull/860) +- :star2: New `PHPCompatibility.Syntax.RemovedCurlyBraceArrayAccess` sniff to detect array and string offset access using curly braces as will be deprecated as of PHP 7.4. [#855](https://github.com/PHPCompatibility/PHPCompatibility/pull/855) + - In contrast to any other sniff in the PHPCompatibility standard, this sniff contains an auto-fixer. +- :star2: New `PHPCompatibility.TextStrings.NewUnicodeEscapeSequence` sniff to detect use of the PHP 7.0+ unicode codepoint escape sequences and issues with invalid sequences. [#856](https://github.com/PHPCompatibility/PHPCompatibility/pull/856) +- :star2: New `PHPCompatibility.Upgrade.LowPHP` sniff to give users of old PHP versions advance warning when support will be dropped in the near future. [#838](https://github.com/PHPCompatibility/PHPCompatibility/pull/838) + At this moment, the intention is to drop support for PHP 5.3 by the end of this year. +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `WeakReference` class as introduced in PHP 7.4. [#857](https://github.com/PHPCompatibility/PHPCompatibility/pull/857) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of new Curl constants as introduced in PHP 7.3.5. [#878](https://github.com/PHPCompatibility/PHPCompatibility/pull/878) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the revived `T_BAD_CHARACTER` constant as re-introduced in PHP 7.4. [#882](https://github.com/PHPCompatibility/PHPCompatibility/pull/882) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the new `IMG_FILTER_SCATTER` and `PASSWORD_ARGON2_PROVIDER` constants as introduced in PHP 7.4. [#887](https://github.com/PHPCompatibility/PHPCompatibility/pull/887) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: detection of use of the `CURLPIPE_HTTP1` constant which will be deprecated in PHP 7.4. [#879](https://github.com/PHPCompatibility/PHPCompatibility/pull/879) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: detection of use of the `FILTER_SANITIZE_MAGIC_QUOTES` constant which will be deprecated in PHP 7.4. [#845](https://github.com/PHPCompatibility/PHPCompatibility/pull/845) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: detection of use of the `T_CHARACTER` and `T_BAD_CHARACTER` constants which were removed in PHP 7.0. [#882](https://github.com/PHPCompatibility/PHPCompatibility/pull/882) +- :star: `PHPCompatibility.FunctionDeclarations.NewMagicMethods` sniff: recognize the new `__serialize()` and `__unserialize()` magic methods as introduced in PHP 7.4. [#868](https://github.com/PHPCompatibility/PHPCompatibility/pull/868) +- :star: `PHPCompatibility.FunctionDeclarations.NewMagicMethods` sniff: recognize the PHP 5.0 `__construct()` and `__destruct()` magic methods. [#884](https://github.com/PHPCompatibility/PHPCompatibility/pull/884) +- :star: `PHPCompatibility.FunctionDeclarations.NonStaticMagicMethods` sniff: recognize the new `__serialize()` and `__unserialize()` magic methods as introduced in PHP 7.4. [#868](https://github.com/PHPCompatibility/PHPCompatibility/pull/868) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize the new PHP 7.4 function `imagecreatefromtga()`. [#873](https://github.com/PHPCompatibility/PHPCompatibility/pull/873) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctionParameters` sniff: recognize the deprecation of the `$age` parameter of the `curl_version()` function. [#874](https://github.com/PHPCompatibility/PHPCompatibility/pull/874) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the PHP 7.4 deprecated `convert_cyr_string()()`, `ezmlm_hash()`, `get_magic_quotes_gpc()`, `get_magic_quotes_runtime()`, `hebrevc()`, `is_real()`, `money_format()` and `restore_include_path()` functions. [#847](https://github.com/PHPCompatibility/PHPCompatibility/pull/847) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: detect use of the new PHP 7.4 `zend.exception_ignore_args` ini directive. [#871](https://github.com/PHPCompatibility/PHPCompatibility/pull/871) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectives` sniff: detect use of the `allow_url_include` ini directive which is deprecated as of PHP 7.4. [#870](https://github.com/PHPCompatibility/PHPCompatibility/pull/870) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectives` sniff: detection of use of the `opcache.load_comments` directive which was removed in PHP 7.0. [#883](https://github.com/PHPCompatibility/PHPCompatibility/pull/883) +- :star: `PHPCompatibility.ParameterValues.NewHashAlgorithms`: recognize use of the new PHP 7.4 `crc32c` hash algorithm. [#872](https://github.com/PHPCompatibility/PHPCompatibility/pull/872) +- :star: `PHPCompatibility.TypeCasts.RemovedTypeCasts` sniff: detect usage of the `(real)` type cast which will be deprecated in PHP 7.4. [#844](https://github.com/PHPCompatibility/PHPCompatibility/pull/844) +- :star: Recognize the `recode` extension functionality which will be removed in PHP 7.4 (moved to PECL) in the `RemovedExtensions` and `RemovedFunctions` sniffs. [#841](https://github.com/PHPCompatibility/PHPCompatibility/pull/841) +- :star: Recognize the `OPcache` extension functionality which was be introduced in PHP 5.5, but not yet fully accounted for in the `NewFunctions` and `NewIniDirectives` sniffs. [#883](https://github.com/PHPCompatibility/PHPCompatibility/pull/883) +- :star: New `getCompleteTextString()` utility method to the `PHPCompatibility\Sniff` class. [#856](https://github.com/PHPCompatibility/PHPCompatibility/pull/856) +- :umbrella: Unit test for the `PHPCompatibility.Upgrade.LowPHPCS` sniff. +- :umbrella: Some extra unit tests for the `PHPCompatibility.ParameterValues.NewNegativeStringOffset`, `PHPCompatibility.ParameterValues.RemovedMbStringModifiers` and sniffs. [#876](https://github.com/PHPCompatibility/PHPCompatibility/pull/876), [#877](https://github.com/PHPCompatibility/PHPCompatibility/pull/877) +- :books: `CONTRIBUTING.md`: Added a list of typical sources for information about changes to PHP. [#875](https://github.com/PHPCompatibility/PHPCompatibility/pull/875) + +### Changed +- :pushpin: `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff: the sniff will now also examine the function docblock, if available, and will throw an error when a `@throws` tag is found in the docblock. [#880](https://github.com/PHPCompatibility/PHPCompatibility/pull/880). Fixes [#863](https://github.com/PHPCompatibility/PHPCompatibility/issues/863) +- :pushpin: `PHPCompatibility.FunctionDeclarations.NonStaticMagicMethods` sniff: will now also check the visibility and `static` (or not) requirements of the magic `__construct()`, `__destruct()`, `__clone()`, `__debugInfo()`, `__invoke()` and `__set_state()` methods. [#885](https://github.com/PHPCompatibility/PHPCompatibility/pull/885) +- :pushpin: `PHPCompatibility.Syntax.NewArrayStringDereferencing` sniff: the sniff will now also recognize array string dereferencing using curly braces as was (silently) supported since PHP 7.0. [#851](https://github.com/PHPCompatibility/PHPCompatibility/pull/851) + - The sniff will now also throw errors for each dereference found on the array/string, not just the first one. +- :pushpin: `PHPCompatibility.Syntax.NewClassMemberAccess` sniff: the sniff will now also recognize class member access on instantiation and cloning using curly braces as was (silently) supported since PHP 7.0. [#852](https://github.com/PHPCompatibility/PHPCompatibility/pull/852) + - The sniff will now also throw errors for each access detected, not just the first one. + - The line number on which the error is thrown in now set more precisely. +- :pushpin: `PHPCompatibility.Syntax.NewFunctionArrayDereferencing` sniff: the sniff will now also recognize function array dereferencing using curly braces as was (silently) supported since PHP 7.0. [#853](https://github.com/PHPCompatibility/PHPCompatibility/pull/853) + - The sniff will now also throw errors for each access detected, not just the first one. + - The line number on which the error is thrown in now set more precisely. +- :recycle: Various code clean-up and improvements. [#849](https://github.com/PHPCompatibility/PHPCompatibility/pull/849), [#850](https://github.com/PHPCompatibility/PHPCompatibility/pull/850) +- :recycle: Various minor inline documentation fixes. [#854](https://github.com/PHPCompatibility/PHPCompatibility/pull/854), [#886](https://github.com/PHPCompatibility/PHPCompatibility/pull/886) +- :wrench: Travis: various tweaks to the build script. [#834](https://github.com/PHPCompatibility/PHPCompatibility/pull/834), [#842](https://github.com/PHPCompatibility/PHPCompatibility/pull/842) + +### Fixed +- :bug: `PHPCompatibility.FunctionDeclarations.ForbiddenParametersWithSameName` sniff: variable names are case-sensitive, so recognition of same named parameters should be done in a case-sensitive manner. [#848](https://github.com/PHPCompatibility/PHPCompatibility/pull/848) +- :bug: `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff: Exceptions thrown within a `try` should not trigger the sniff. [#880](https://github.com/PHPCompatibility/PHPCompatibility/pull/880). Fixes [#863](https://github.com/PHPCompatibility/PHPCompatibility/issues/863) +- :bug: `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff: the `$ooScopeTokens` property should never have been a public property. [#880](https://github.com/PHPCompatibility/PHPCompatibility/pull/880). +- :umbrella: Some of the unit tests for the `PHPCompatibility.Operators.RemovedTernaryAssociativity` sniff were not being run. [#836](https://github.com/PHPCompatibility/PHPCompatibility/pull/836) + + +## [9.2.0] - 2019-06-28 + +See all related issues and PRs in the [9.2.0 milestone]. + +To keep informed of the progress of covering "_everything PHP 7.4_" in PHPCompatibility, please subscribe to issue [#808](https://github.com/PHPCompatibility/PHPCompatibility/issues/808). + +### Added +- :star2: New `PHPCompatibility.Classes.ForbiddenAbstractPrivateMethods` sniff to detect methods declared as both `private` as well as `abstract`. This was allowed between PHP 5.0.0 and 5.0.4, but disallowed in PHP 5.1 as the behaviour of `private` and `abstract` are mutually exclusive. [#822](https://github.com/PHPCompatibility/PHPCompatibility/pull/822) +- :star2: New `PHPCompatibility.Classes.NewTypedProperties` sniff to detect PHP 7.4 typed property declarations. [#801](https://github.com/PHPCompatibility/PHPCompatibility/pull/801), [#829](https://github.com/PHPCompatibility/PHPCompatibility/pull/829) +- :star2: New `PHPCompatibility.Classes.RemovedOrphanedParent` sniff to detect the use of the `parent` keyword in classes without a parent (non-extended classes). This code pattern is deprecated in PHP 7.4 and will become a compile-error in PHP 8.0. [#818](https://github.com/PHPCompatibility/PHPCompatibility/pull/818) +- :star2: New `PHPCompatibility.FunctionDeclarations.NewExceptionsFromToString` sniff to detect throwing exceptions from `__toString()` methods. This would previously result in a fatal error, but will be allowed as of PHP 7.4. [#814](https://github.com/PHPCompatibility/PHPCompatibility/pull/814) +- :star2: New `PHPCompatibility.FunctionDeclarations.ForbiddenToStringParameters` sniff to detect `__toString()` function declarations expecting parameters. This was disallowed in PHP 5.3. [#815](https://github.com/PHPCompatibility/PHPCompatibility/pull/815) +- :star2: New `PHPCompatibility.MethodUse.ForbiddenToStringParameters` sniff to detect direct calls to `__toString()` magic methods passing parameters. This was disallowed in PHP 5.3. [#830](https://github.com/PHPCompatibility/PHPCompatibility/pull/830) +- :star2: New `PHPCompatibility.Operators.ChangedConcatOperatorPrecedence` sniff to detect code affected by the upcoming change in operator precedence for the concatenation operator. The concatenation operator precedence will be lowered in PHP 8.0, with deprecation notices for code affected being thrown in PHP 7.4. [#805](https://github.com/PHPCompatibility/PHPCompatibility/pull/805) +- :star2: New `PHPCompatibility.Operators.RemovedTernaryAssociativity` sniff to detect code relying on left-associativity of the ternary operator. This behaviour will be deprecated in PHP 7.4 and removed in PHP 8.0. [#810](https://github.com/PHPCompatibility/PHPCompatibility/pull/810) +- :star2: New `PHPCompatibility.Syntax.NewArrayUnpacking` sniff to detect the use of the spread operator to unpack arrays when declaring a new array, as introduced in PHP 7.4. [#804](https://github.com/PHPCompatibility/PHPCompatibility/pull/804) +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `ReflectionReference` class as introduced in PHP 7.4. [#820](https://github.com/PHPCompatibility/PHPCompatibility/pull/820) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: detection of the new PHP 7.4 Core (Standard), MBString, Socket and Tidy constants. [#821](https://github.com/PHPCompatibility/PHPCompatibility/pull/821) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: detect usage of the new PHP 7.4 `get_mangled_object_vars()`, `mb_str_split()`, `openssl_x509_verify()`, `password_algos()`, `pcntl_unshare()`, `sapi_windows_set_ctrl_handler()` and `sapi_windows_generate_ctrl_event()` functions. [#811](https://github.com/PHPCompatibility/PHPCompatibility/pull/811), [#819](https://github.com/PHPCompatibility/PHPCompatibility/pull/819), [#827](https://github.com/PHPCompatibility/PHPCompatibility/pull/827) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize the new OCI functions as introduced in PHP 7.2.14 and PHP 7.3.1. [#786](https://github.com/PHPCompatibility/PHPCompatibility/pull/786) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the PHP 7.4 deprecated `ldap_control_paged_result_response()` and `ldap_control_paged_result()` functions. [#831](https://github.com/PHPCompatibility/PHPCompatibility/pull/831) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the `Payflow Pro/pfpro` functions as removed in PHP 5.1. [#823](https://github.com/PHPCompatibility/PHPCompatibility/pull/823) +- :star: `PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters` sniff: account for the parameters for `array_merge()` and `array_merge_recursive()` becoming optional in PHP 7.4. [#817](https://github.com/PHPCompatibility/PHPCompatibility/pull/817) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectives` sniff: recognize the `Payflow Pro/pfpro` ini directives as removed in PHP 5.1. [#823](https://github.com/PHPCompatibility/PHPCompatibility/pull/823) +- :star: Recognize the `interbase/Firebird` extension functionality which will be removed in PHP 7.4 (moved to PECL) in the `RemovedConstants`, `RemovedExtensions`, `RemovedFunctions` and `RemovedIniDirectives` sniffs. [#807](https://github.com/PHPCompatibility/PHPCompatibility/pull/807) +- :star: Recognize the `wddx` extension functionality which will be removed in PHP 7.4 (moved to PECL) in the `RemovedExtensions` and `RemovedFunctions` sniffs. [#826](https://github.com/PHPCompatibility/PHPCompatibility/pull/826) +- :star: New `isShortTernary()` and `isUnaryPlusMinus()` utility methods to the `PHPCompatibility\Sniff` class. [#810](https://github.com/PHPCompatibility/PHPCompatibility/pull/810), [#805](https://github.com/PHPCompatibility/PHPCompatibility/pull/805) + +### Changed +- :pencil2: The `PHPCompatibility.Extensions.RemovedExtensions` sniff will now only report on the removed `Payflow Pro` extension when a function uses `pfpro_` as a prefix. Previously, it used the `pfpro` prefix (without underscore) for detection. [#812](https://github.com/PHPCompatibility/PHPCompatibility/pull/812) +- :pencil2: The error message thrown when the `T_ELLIPSIS` token, i.e. the spread operator, is detected. [#803](https://github.com/PHPCompatibility/PHPCompatibility/pull/803) + PHP 7.4 adds a third use-case for the spread operator. The adjusted error message accounts for this. +- :umbrella: `PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations` is now also tested with parameters using the splat operator. [#802](https://github.com/PHPCompatibility/PHPCompatibility/pull/802) +- :books: The documentation now uses the GitHub repo of `PHP_CodeSniffer` as the canonical entry point for `PHP_CodeSniffer`. Previously, it would point to the PEAR package. [#788](https://github.com/PHPCompatibility/PHPCompatibility/pull/788) +- :books: The links in the changelog now all point to the `PHPCompatibility/PHPCompatibility` repo and no longer to the (deprecated) `wimg/PHPCompatibility` repo. [#828](https://github.com/PHPCompatibility/PHPCompatibility/pull/828) +- :recycle: Various minor inline documentation improvements. [#825](https://github.com/PHPCompatibility/PHPCompatibility/pull/825) +- :wrench: Various performance optimizations and code simplifications. [#783](https://github.com/PHPCompatibility/PHPCompatibility/pull/783), [#784](https://github.com/PHPCompatibility/PHPCompatibility/pull/784), [#795](https://github.com/PHPCompatibility/PHPCompatibility/pull/795), [#813](https://github.com/PHPCompatibility/PHPCompatibility/pull/813) +- :green_heart: Travis: build tests are now being run against PHP 7.4 (unstable) as well. [#790](https://github.com/PHPCompatibility/PHPCompatibility/pull/790) + Note: the builds are currently not (yet) tested against PHP 8.0 (unstable) as there is no compatible PHPUnit version available (yet). +- :wrench: Travis: The build script has been refactored to use [stages](https://docs.travis-ci.com/user/build-stages/) to get the most relevant results faster. Additionally some more tweaks have been made to improve and/or simplify the build script. [#798](https://github.com/PHPCompatibility/PHPCompatibility/pull/798) +- :wrench: Build/PHPCS: warnings are no longer allowed for the PHPCompatibility native code. [#800](https://github.com/PHPCompatibility/PHPCompatibility/pull/800) +- :wrench: Build/PHPCS: added variable assignment alignment check and file include check to the PHPCompatibility native CS configuration. [#824](https://github.com/PHPCompatibility/PHPCompatibility/pull/824) +- :wrench: The minimum version for the recommended `DealerDirect/phpcodesniffer-composer-installer` Composer plugin has been upped to `0.5.0`. [#791](https://github.com/PHPCompatibility/PHPCompatibility/pull/791) + +### Fixed +- :bug: The `PHPCompatibility.Extensions.RemovedExtensions` sniff contained a typo in the alternative recommended for the removed `mcve` extension. [#806](https://github.com/PHPCompatibility/PHPCompatibility/pull/806) +- :bug: The `PHPCompatibility.Extensions.RemovedExtensions` sniff listed the wrong removal version number for the `Payflow Pro/pfpro` extension (PHP 5.3 instead of the correct 5.1). [#823](https://github.com/PHPCompatibility/PHPCompatibility/pull/823) + +### Credits +Thanks go out to [Yılmaz] and [Tim Millwood] for their contribution to this version. :clap: + + +## [9.1.1] - 2018-12-31 + +See all related issues and PRs in the [9.1.1 milestone]. + +### Fixed +- :bug: `ForbiddenThisUseContexts`: false positive for unsetting `$this['key']` on objects implementing `ArrayAccess`. [#781](https://github.com/PHPCompatibility/PHPCompatibility/pull/781). Fixes [#780](https://github.com/PHPCompatibility/PHPCompatibility/issues/780) + +## [9.1.0] - 2018-12-16 + +See all related issues and PRs in the [9.1.0 milestone]. + +### Added +- :star2: New `PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue` sniff to detect code which could be affected by the PHP 7.0 change in the values reported by `func_get_arg()`, `func_get_args()`, `debug_backtrace()` and exception backtraces. [#750](https://github.com/PHPCompatibility/PHPCompatibility/pull/750). Fixes [#585](https://github.com/PHPCompatibility/PHPCompatibility/pull/585). +- :star2: New `PHPCompatibility.MethodUse.NewDirectCallsToClone` sniff to detect direct call to a `__clone()` magic method which wasn't allowed prior to PHP 7.0. [#743](https://github.com/PHPCompatibility/PHPCompatibility/pull/743). Fixes [#629](https://github.com/PHPCompatibility/PHPCompatibility/issues/629). +- :star2: New `PHPCompatibility.Variables.ForbiddenThisUseContext` sniff to detect most of the inconsistencies surrounding the use of the `$this` variable, which were removed in PHP 7.1. [#762](https://github.com/PHPCompatibility/PHPCompatibility/pull/762), [#771](https://github.com/PHPCompatibility/PHPCompatibility/pull/771). Fixes [#262](https://github.com/PHPCompatibility/PHPCompatibility/issues/262) and [#740](https://github.com/PHPCompatibility/PHPCompatibility/issues/740). +- :star: `NewClasses`: detection of more native PHP Exceptions. [#743](https://github.com/PHPCompatibility/PHPCompatibility/pull/743), [#753](https://github.com/PHPCompatibility/PHPCompatibility/pull/753) +- :star: `NewConstants` : detection of the new PHP 7.3 Curl, Stream Crypto and LDAP constants and some more PHP 7.0 Tokenizer constants. [#752](https://github.com/PHPCompatibility/PHPCompatibility/pull/752), [#767](https://github.com/PHPCompatibility/PHPCompatibility/pull/767), [#778](https://github.com/PHPCompatibility/PHPCompatibility/pull/778) +- :star: `NewFunctions` sniff: recognize (more) new LDAP functions as introduced in PHP 7.3. [#768](https://github.com/PHPCompatibility/PHPCompatibility/pull/768) +- :star: `NewFunctionParameters` sniff: recognize the new `$serverctrls` parameter which was added to a number of LDAP functions in PHP 7.3. [#769](https://github.com/PHPCompatibility/PHPCompatibility/pull/769) +- :star: `NewIniDirectives` sniff: recognize the new `imap.enable_insecure_rsh` ini directive as introduced in PHP 7.1.25, 7.2.13 and 7.3.0. [#770](https://github.com/PHPCompatibility/PHPCompatibility/pull/770) +- :star: `NewInterfaces` sniff: recognize two more Session related interfaces which were introduced in PHP 5.5.1 and 7.0 respectively. [#748](https://github.com/PHPCompatibility/PHPCompatibility/pull/748) +- :star: Duplicate of upstream `findStartOfStatement()` method to the `PHPCompatibility\PHPCSHelper` class to allow for PHPCS cross-version usage of that method. [#750](https://github.com/PHPCompatibility/PHPCompatibility/pull/750) + +### Changed +- :pushpin: `RemovedPHP4StyleConstructors`: will now also detect PHP4-style constructors when declared in interfaces. [#751](https://github.com/PHPCompatibility/PHPCompatibility/pull/751) +- :pushpin: `Sniff::validDirectScope()`: the return value of this method has changed. Previously it would always be a boolean. It will stil return `false` when no valid direct scope has been found, but it will now return the `stackPtr` to the scope token if a _valid_ direct scope was encountered. [#758](https://github.com/PHPCompatibility/PHPCompatibility/pull/758) +- :rewind: `NewOperators` : updated the version number for `T_COALESCE_EQUAL`. [#746](https://github.com/PHPCompatibility/PHPCompatibility/pull/746) +- :pencil: Minor improvement to an error message in the unit test suite. [#742](https://github.com/PHPCompatibility/PHPCompatibility/pull/742) +- :recycle: Various code clean-up and improvements. [#745](https://github.com/PHPCompatibility/PHPCompatibility/pull/745), [#756](https://github.com/PHPCompatibility/PHPCompatibility/pull/756), [#774](https://github.com/PHPCompatibility/PHPCompatibility/pull/774) +- :recycle: Various minor inline documentation fixes. [#749](https://github.com/PHPCompatibility/PHPCompatibility/pull/749), [#757](https://github.com/PHPCompatibility/PHPCompatibility/pull/757) +- :umbrella: Improved code coverage recording. [#744](https://github.com/PHPCompatibility/PHPCompatibility/pull/744), [#776](https://github.com/PHPCompatibility/PHPCompatibility/pull/776) +- :green_heart: Travis: build tests are now being run against PHP 7.3 as well. [#511](https://github.com/PHPCompatibility/PHPCompatibility/pull/511) + Note: full PHP 7.3 support is only available in combination with PHP_CodeSniffer 2.9.2 or 3.3.1+ due to an incompatibility within PHP_CodeSniffer itself. + +### Fixed +- :white_check_mark: Compatibility with the upcoming release of PHPCS 3.4.0. Deal with changed behaviour of the PHPCS `Tokenizer` regarding binary type casts. [#760](https://github.com/PHPCompatibility/PHPCompatibility/pull/760) +- :bug: `InternalInterfaces`: false negative for implemented/extended interfaces prefixed with a namespace separator. [#775](https://github.com/PHPCompatibility/PHPCompatibility/pull/775) +- :bug: `NewClasses`: the introduction version of various native PHP Exceptions has been corrected. [#743](https://github.com/PHPCompatibility/PHPCompatibility/pull/743), [#753](https://github.com/PHPCompatibility/PHPCompatibility/pull/753) +- :bug: `NewInterfaces`: false negative for implemented/extended interfaces prefixed with a namespace separator. [#775](https://github.com/PHPCompatibility/PHPCompatibility/pull/775) +- :bug: `RemovedPHP4StyleConstructors`: the sniff would examine methods in nested anonymous classes as if they were methods of the higher level class. [#751](https://github.com/PHPCompatibility/PHPCompatibility/pull/751) +- :rewind: `RemovedPHP4StyleConstructors`: the sniff will no longer throw false positives for the first method in an anonymous class when used in combination with PHPCS 2.3.x. [#751](https://github.com/PHPCompatibility/PHPCompatibility/pull/751) +- :rewind: `ReservedFunctionNames`: fixed incorrect error message text for methods in anonymous classes when used in combination with PHPCS 2.3.x. [#755](https://github.com/PHPCompatibility/PHPCompatibility/pull/755) +- :bug: `ReservedFunctionNames`: prevent duplicate errors being thrown for methods in nested anonymous classes. [#755](https://github.com/PHPCompatibility/PHPCompatibility/pull/755) +- :bug: `PHPCSHelper::findEndOfStatement()`: minor bug fix. [#749](https://github.com/PHPCompatibility/PHPCompatibility/pull/749) +- :bug: `Sniff::isClassProperty()`: class properties for classes nested in conditions or function calls were not always recognized as class properties. [#758](https://github.com/PHPCompatibility/PHPCompatibility/pull/758) + +### Credits +Thanks go out to [Jonathan Champ] for his contribution to this version. :clap: + + +## [9.0.0] - 2018-10-07 + +**IMPORTANT**: This release contains **breaking changes**. Please read the below information carefully before upgrading! + +All sniffs have been placed in meaningful categories and a number of sniffs have been renamed to have more consistent, meaningful and future-proof names. + +Both the `PHPCompatibilityJoomla` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityJoomla) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-joomla)] as well as the `PHPCompatibilityWP` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityWP)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp)] rulesets have already been adjusted for this change and have released a new version which is compatible with this version of PHPCompatibility. + +Aside from those CMS-based rulesets, this project now also offers a number of polyfill-library specific rulesets, such as `PHPCompatibilityPasswordCompat` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityPasswordCompat) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-passwordcompat)] for @ircmaxell's [`password_compat`](https://github.com/ircmaxell/password_compat) libary, `PHPCompatibilityParagonieRandomCompat` and `PHPCompatibilityParagonieSodiumCompat` [[GH](https://github.com/PHPCompatibility/PHPCompatibilityParagonie)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie)] for the [Paragonie polyfills](https://github.com/paragonie?utf8=?&q=polyfill) and a number of rulesets related to various [polyfills offered by the Symfony project](https://github.com/symfony?utf8=?&q=polyfill) [[GH](https://github.com/PHPCompatibility/PHPCompatibilitySymfony)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-symfony)]. + +If your project uses one of these polyfills, please consider using these special polyfill rulesets to prevent false positives. + +Also as of this version, [Juliette Reinders Folmer] is now officially a co-maintainer of this package. + +### Upgrade instructions + +* If you have `` directives in your own project's custom ruleset which relate to sniffs from the PHPCompatibility library, you will need to update your ruleset to use the new sniff names. +* If you use the new [PHPCS 3.2+ inline annotations](https://github.com/squizlabs/PHP_CodeSniffer/releases/3.2.0), i.e. `// phpcs:ignore Standard.Category.SniffName`, in combination with PHPCompatibility sniff names, you will need to update these annotations. +* If you use neither of the above, you should be fine and upgrading should be painless. + +### Overview of all the sniff renames: + +Old Category.SniffName | New Category.SniffName +--- | --- +**PHP**.ArgumentFunctionsUsage | **FunctionUse**.ArgumentFunctionsUsage +**PHP**.CaseSensitiveKeywords | **Keywords**.CaseSensitiveKeywords +**PHP**.ConstantArraysUsingConst | **InitialValue**.**New**ConstantArraysUsingConst +**PHP**.ConstantArraysUsingDefine | **InitialValue**.**New**ConstantArraysUsingDefine +**PHP**.**Deprecated**Functions | **FunctionUse**.**Removed**Functions +**PHP**.**Deprecated**IniDirectives | **IniDirectives**.**Removed**IniDirectives +**PHP**.**Deprecated**MagicAutoload | **FunctionNameRestrictions**.**Removed**MagicAutoload +**PHP**.**Deprecated**NewReference | **Syntax**.**Removed**NewReference +**PHP**.**Deprecated**PHP4StyleConstructors | **FunctionNameRestrictions**.**Removed**PHP4StyleConstructors +**PHP**.**Deprecated**TypeCasts | **TypeCasts**.**Removed**TypeCasts +**PHP**.DiscouragedSwitchContinue | **ControlStructures**.DiscouragedSwitchContinue +**PHP**.DynamicAccessToStatic | **Syntax**.**New**DynamicAccessToStatic +**PHP**.EmptyNonVariable | **LanguageConstructs**.**New**EmptyNonVariable +**PHP**.ForbiddenBreakContinueOutsideLoop | **ControlStructures**.ForbiddenBreakContinueOutsideLoop +**PHP**.ForbiddenBreakContinueVariableArguments | **ControlStructures**.ForbiddenBreakContinueVariableArguments +**PHP**.ForbiddenCallTimePassByReference | **Syntax**.ForbiddenCallTimePassByReference +**PHP**.Forbidden**ClosureUseVariableNames** | **FunctionDeclarations**.Forbidden**VariableNamesInClosureUse** +**PHP**.ForbiddenEmptyListAssignment | **Lists**.ForbiddenEmptyListAssignment +**PHP**.Forbidden**Function**ParametersWithSameName | **FunctionDeclarations**.ForbiddenParametersWithSameName +**PHP**.ForbiddenGlobalVariableVariable | **Variables**.ForbiddenGlobalVariableVariable +**PHP**.ForbiddenNames | **Keywords**.ForbiddenNames +**PHP**.ForbiddenNamesAsDeclared | **Keywords**.ForbiddenNamesAsDeclared +**PHP**.ForbiddenNamesAsInvokedFunctions | **Keywords**.ForbiddenNamesAsInvokedFunctions +**PHP**.ForbiddenNegativeBitshift | **Operators**.ForbiddenNegativeBitshift +**PHP**.ForbiddenSwitchWithMultipleDefaultBlocks | **ControlStructures**.ForbiddenSwitchWithMultipleDefaultBlocks +**PHP**.InternalInterfaces | **Interfaces**.InternalInterfaces +**PHP**.LateStaticBinding | **Classes**.**New**LateStaticBinding +**PHP**.**MbstringReplaceE**Modifier | **ParameterValues**.**RemovedMbstring**Modifier**s** +**PHP**.NewAnonymousClasses | **Classes**.NewAnonymousClasses +**PHP**.NewArrayStringDereferencing | **Syntax**.NewArrayStringDereferencing +**PHP**.NewClasses | **Classes**.NewClasses +**PHP**.NewClassMemberAccess | **Syntax**.NewClassMemberAccess +**PHP**.NewClosure | **FunctionDeclarations**.NewClosure +**PHP**.NewConstants | **Constants**.NewConstants +**PHP**.NewConstantScalarExpressions | **InitialValue**.NewConstantScalarExpressions +**PHP**.NewConstVisibility | **Classes**.NewConstVisibility +**PHP**.NewExecutionDirectives | **ControlStructures**.NewExecutionDirectives +**PHP**.NewFunctionArrayDereferencing | **Syntax**.NewFunctionArrayDereferencing +**PHP**.NewFunctionParameters | **FunctionUse**.NewFunctionParameters +**PHP**.NewFunctions | **FunctionUse**.NewFunctions +**PHP**.NewGeneratorReturn | **Generators**.NewGeneratorReturn +**PHP**.NewGroupUseDeclarations | **UseDeclarations**.NewGroupUseDeclarations +**PHP**.NewHashAlgorithms | **ParameterValues**.NewHashAlgorithms +**PHP**.NewHeredoc**Initialize** | **InitialValue**.NewHeredoc +**PHP**.NewIniDirectives | **IniDirectives**.NewIniDirectives +**PHP**.NewInterfaces | **Interfaces**.NewInterfaces +**PHP**.NewKeywords | **Keywords**.NewKeywords +**PHP**.NewLanguageConstructs | **LanguageConstructs**.NewLanguageConstructs +**PHP**.NewMagicClassConstant | **Constants**.NewMagicClassConstant +**PHP**.NewMagicMethods | **FunctionNameRestrictions**.NewMagicMethods +**PHP**.NewMultiCatch | **ControlStructures**.NewMultiCatch +**PHP**.NewNullableTypes | **FunctionDeclarations**.NewNullableTypes +**PHP**.NewReturnTypeDeclarations | **FunctionDeclarations**.NewReturnTypeDeclarations +**PHP**.New**Scalar**TypeDeclarations | **FunctionDeclarations**.New**Param**TypeDeclarations +**PHP**.NewTrailingComma | **Syntax**.New**FunctionCall**TrailingComma +**PHP**.NewTypeCasts | **TypeCasts**.NewTypeCasts +**PHP**.NewUseConstFunction | **UseDeclarations**.NewUseConstFunction +**PHP**.NonStaticMagicMethods | **FunctionDeclarations**.NonStaticMagicMethods +**PHP**.OptionalRequiredFunctionParameters | **FunctionUse**.Optional**To**RequiredFunctionParameters +**PHP**.ParameterShadowSuperGlobals | **FunctionDeclarations**.**Forbidden**ParameterShadowSuperGlobals +**PHP**.**PCRENew**Modifiers | **ParameterValues**.**NewPCRE**Modifiers +**PHP**.**PregReplaceE**Modifier | **ParameterValues**.**RemovedPCRE**Modifier**s** +**PHP**.RemovedAlternativePHPTags | **Miscellaneous**.RemovedAlternativePHPTags +**PHP**.RemovedConstants | **Constants**.RemovedConstants +**PHP**.RemovedExtensions | **Extensions**.RemovedExtensions +**PHP**.RemovedFunctionParameters | **FunctionUse**.RemovedFunctionParameters +**PHP**.RemovedGlobalVariables | **Variables**.Removed**Predefined**GlobalVariables +**PHP**.RemovedHashAlgorithms | **ParameterValues**.RemovedHashAlgorithms +**PHP**.ReservedFunctionNames | **FunctionNameRestrictions**.ReservedFunctionNames +**PHP**.RequiredOptionalFunctionParameters | **FunctionUse**.Required**To**OptionalFunctionParameters +**PHP**.ShortArray | **Syntax**.**New**ShortArray +**PHP**.Ternary**Operators** | **Operators**.**NewShort**Ternary +**PHP**.ValidIntegers | **Miscellaneous**.ValidIntegers +**PHP**.**VariableVariables** | **Variables**.**NewUniformVariableSyntax** + +### Changelog for version 9.0.0 + +See all related issues and PRs in the [9.0.0 milestone]. + +### Added +- :star2: New `PHPCompatibility.ControlStructures.NewForeachExpressionReferencing` sniff to detect referencing of `$value` within a `foreach()` when the iterated array is not a variable. This was not supported prior to PHP 5.5. [#664](https://github.com/PHPCompatibility/PHPCompatibility/pull/664) +- :star2: New `PHPCompatibility.ControlStructures.NewListInForeach` sniff to detect unpacking nested arrays into separate variables via the `list()` construct in a `foreach()` statement. This was not supported prior to PHP 5.5. [#657](https://github.com/PHPCompatibility/PHPCompatibility/pull/657) +- :star2: New `PHPCompatibility.FunctionNameRestrictions.RemovedNamespacedAssert` sniff to detect declaring a function called `assert()` within a namespace. This has been deprecated as of PHP 7.3. [#735](https://github.com/PHPCompatibility/PHPCompatibility/pull/735). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star2: New `PHPCompatibility.Lists.AssignmentOrder` sniff to detect `list()` constructs affected by the change in assignment order in PHP 7.0. [#656](https://github.com/PHPCompatibility/PHPCompatibility/pull/656) +- :star2: New `PHPCompatibility.Lists.NewKeyedList` sniff to detect usage of keys in `list()`, support for which was added in PHP 7.1. [#655](https://github.com/PHPCompatibility/PHPCompatibility/pull/655). Fixes [#252](https://github.com/PHPCompatibility/PHPCompatibility/issues/252). +- :star2: New `PHPCompatibility.Lists.NewListReferenceAssignment` sniff to detect reference assignments being used in `list()` constructs, support for which has been added in PHP 7.3. [#731](https://github.com/PHPCompatibility/PHPCompatibility/pull/731) +- :star2: New `PHPCompatibility.Lists.NewShortList` sniff to detect the shorthand array syntax `[]` being used for symmetric array destructuring as introduced in PHP 7.1. [#654](https://github.com/PHPCompatibility/PHPCompatibility/pull/654). Fixes [#248](https://github.com/PHPCompatibility/PHPCompatibility/issues/248). +- :star2: New `PHPCompatibility.Operators.NewOperators` sniff which checks for usage of the pow, pow equals, spaceship and coalesce (equals) operators. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + These checks were previously contained within the `PHPCompatibility.LanguageConstructs.NewLanguageConstructs` sniff. +- :star2: New `PHPCompatibility.ParameterValues.ForbiddenGetClassNull` sniff to detect `null` being passed to `get_class()`, support for which has been removed in PHP 7.2 [#659](https://github.com/PHPCompatibility/PHPCompatibility/pull/659). Fixes [#557](https://github.com/PHPCompatibility/PHPCompatibility/issues/557). +- :star2: New `PHPCompatibility.ParameterValues.NewArrayReduceInitialType` sniff to detect non-integers being passed as the `$initial` parameter to the `array_reduce()` function, which was not supported before PHP 5.3. [#666](https://github.com/PHPCompatibility/PHPCompatibility/pull/666). Fixes [#649](https://github.com/PHPCompatibility/PHPCompatibility/issues/649) +- :star2: New `PHPCompatibility.ParameterValues.NewFopenModes` sniff to examine the `$mode` parameter passed to `fopen()` for modes not available in older PHP versions. [#658](https://github.com/PHPCompatibility/PHPCompatibility/pull/658) +- :star2: New `PHPCompatibility.ParameterValues.NewNegativeStringOffset` sniff to detect negative string offsets being passed to string manipulation functions which was not supported before PHP 7.1. [#662](https://github.com/PHPCompatibility/PHPCompatibility/pull/662). Partially fixes [#253](https://github.com/PHPCompatibility/PHPCompatibility/issues/253). +- :star2: New `PHPCompatibility.ParameterValues.NewPackFormats` sniff to examine the `$format` parameter passed to `pack()` for formats not available in older PHP versions. [#665](https://github.com/PHPCompatibility/PHPCompatibility/pull/665) +- :star2: New `PHPCompatibility.ParameterValues.RemovedIconvEncoding` sniff to detect the PHP 5.6 deprecated encoding `$type`s being passed to `iconv_set_encoding()`. [#660](https://github.com/PHPCompatibility/PHPCompatibility/pull/660). Fixes [#475](https://github.com/PHPCompatibility/PHPCompatibility/issues/475). +- :star2: New `PHPCompatibility.ParameterValues.RemovedNonCryptoHashes` sniff to detect non-cryptographic hash algorithms being passed to various `hash_*()` functions. This is no longer accepted as of PHP 7.2. [#663](https://github.com/PHPCompatibility/PHPCompatibility/pull/663). Fixes [#559](https://github.com/PHPCompatibility/PHPCompatibility/issues/559) +- :star2: New `PHPCompatibility.ParameterValues.RemovedSetlocaleString` sniff to detect string literals being passed to the `$category` parameter of the `setlocale()` function. This behaviour was deprecated in PHP 4.2 and support has been removed in PHP 7.0. [#661](https://github.com/PHPCompatibility/PHPCompatibility/pull/661) +- :star2: New `PHPCompatibility.Syntax.NewFlexibleHeredocNowdoc` sniff to detect the new heredoc/nowdoc format as allowed as of PHP 7.3. [#736](https://github.com/PHPCompatibility/PHPCompatibility/pull/736). Fixes [#705](https://github.com/PHPCompatibility/PHPCompatibility/issues/705). + Note: This sniff is only supported in combination with PHP_CodeSniffer 2.6.0 and higher. +- :star: `PHPCompatibility.Classes.NewClasses` sniff: recognize the new `CompileError` and `JsonException` classes as introduced in PHP 7.3. [#676](https://github.com/PHPCompatibility/PHPCompatibility/pull/676) +- :star: `PHPCompatibility.Constants.NewConstants` sniff: recognize new constants which are being introduced in PHP 7.3. [#678](https://github.com/PHPCompatibility/PHPCompatibility/pull/678) +- :star: `PHPCompatibility.Constants.RemovedConstants` sniff: recognize constants which have been deprecated or removed in PHP 7.3. [#710](https://github.com/PHPCompatibility/PHPCompatibility/pull/710). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize various new functions being introduced in PHP 7.3. [#679](https://github.com/PHPCompatibility/PHPCompatibility/pull/679) +- :star: `PHPCompatibility.FunctionUse.NewFunctions` sniff: recognize the `sapi_windows_*()`, `hash_hkdf()` and `pcntl_signal_get_handler()` functions as introduced in PHP 7.1. [#728](https://github.com/PHPCompatibility/PHPCompatibility/pull/728) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctionParameters` sniff: recognize the deprecation of the `$case_insensitive` parameter for the `define()` function in PHP 7.3. [#706](https://github.com/PHPCompatibility/PHPCompatibility/pull/706) +- :star: `PHPCompatibility.FunctionUse.RemovedFunctions` sniff: recognize the PHP 7.3 deprecation of the `image2wbmp()`, `fgetss()` and `gzgetss()` functions, as well as the deprecation of undocumented Mbstring function aliases. [#681](https://github.com/PHPCompatibility/PHPCompatibility/pull/681), [#714](https://github.com/PHPCompatibility/PHPCompatibility/pull/714), [#720](https://github.com/PHPCompatibility/PHPCompatibility/pull/720). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star: `PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters` sniff: account for the second parameter for `array_push()` and `array_unshift()` becoming optional in PHP 7.3, as well as for the `$mode` parameter for a range of `ftp_*()` functions becoming optional. [#680](https://github.com/PHPCompatibility/PHPCompatibility/pull/680) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: recognize new `syslog` and `session` ini directives as introduced in PHP 7.3. [#702](https://github.com/PHPCompatibility/PHPCompatibility/pull/702), [#719](https://github.com/PHPCompatibility/PHPCompatibility/pull/719), [#730](https://github.com/PHPCompatibility/PHPCompatibility/pull/730) +- :star: `PHPCompatibility.IniDirectives.NewIniDirectives` sniff: recognize some more ini directives which were introduced in PHP 7.1. [#727](https://github.com/PHPCompatibility/PHPCompatibility/pull/727) +- :star: `PHPCompatibility.IniDirectives.RemovedIniDirectived` sniff: recognize ini directives removed in PHP 7.3. [#677](https://github.com/PHPCompatibility/PHPCompatibility/pull/677), [#717](https://github.com/PHPCompatibility/PHPCompatibility/pull/717). Partially fixes [#718](https://github.com/PHPCompatibility/PHPCompatibility/issues/718). +- :star: New `isNumericCalculation()` and `isVariable()` utility methods to the `PHPCompatibility\Sniff` class. [#664](https://github.com/PHPCompatibility/PHPCompatibility/pull/664), [#666](https://github.com/PHPCompatibility/PHPCompatibility/pull/666) +- :books: A section about the new sniff naming conventions to the `Contributing` file. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + +### Changed +- :fire: All sniffs have been placed in meaningful categories and a number of sniffs have been renamed to have more consistent, meaningful and future-proof names. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738). Fixes [#601](https://github.com/PHPCompatibility/PHPCompatibility/issues/601), [#692](https://github.com/PHPCompatibility/PHPCompatibility/issues/692) + See the table at the top of this changelog for details of all the file renames. +- :umbrella: The unit test files have been moved about as well. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + * The directory structure for these now mirrors the default directory structure used by PHPCS itself. + * The file names of the unit test files have been adjusted for the changes made in the sniffs. + * The unit test case files have been renamed and moved to the same directory as the actual test file they apply to. + * The `BaseSniffTest::sniffFile()` method has been adjusted to match. The signature of this method has changed. Where it previously expected a relative path to the unit test case file, it now expects an absolute path. + * The unit tests for the utility methods in the `PHPCompatibility\Sniff` class have been moved to a new `PHPCompatibility\Util\Tests\Core` subdirectory. + * The bootstrap file used for PHPUnit has been moved to the project root directory and renamed `phpunit-bootstrap.php`. +- :twisted_rightwards_arrows: The `PHPCompatibility.LanguageConstructs.NewLanguageConstructs` sniff has been split into two sniffs. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) + The `PHPCompatibility.LanguageConstructs.NewLanguageConstructs` sniff now contains just the checks for the namespace separator and the ellipsis. + The new `PHPCompatibility.Operators.NewOperators` sniff now contains the checks regarding the pow, pow equals, spaceship and coalesce (equals) operators. +- :pushpin: The `PHPCompatibility.ParameterValues.RemovedMbstringModifiers` sniff will now also recognize removed regex modifiers when used within a function call to one of the undocumented Mbstring function aliases for the Mbstring regex functions. [#715](https://github.com/PHPCompatibility/PHPCompatibility/pull/715) +- :pushpin: The `PHPCompatibility\Sniff::getFunctionCallParameter()` utility method now allows for closures called via a variable. [#723](https://github.com/PHPCompatibility/PHPCompatibility/pull/723) +- :pencil2: `PHPCompatibility.Upgrade.LowPHPCS`: the minimum supported PHPCS version is now 2.3.0. [#699](https://github.com/PHPCompatibility/PHPCompatibility/pull/699) +- :pencil2: Minor inline documentation improvements. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738) +- :umbrella: Minor improvements to the unit tests for the `PHPCompatibility.FunctionNameRestrctions.RemovedMagicAutoload` sniff. [#716](https://github.com/PHPCompatibility/PHPCompatibility/pull/716) +- :recycle: Minor other optimizations. [#698](https://github.com/PHPCompatibility/PHPCompatibility/pull/698), [#697](https://github.com/PHPCompatibility/PHPCompatibility/pull/697) +- :wrench: Minor improvements to the build tools. [#701](https://github.com/PHPCompatibility/PHPCompatibility/pull/701) +- :wrench: Removed some unnecessary inline annotations. [#700](https://github.com/PHPCompatibility/PHPCompatibility/pull/700) +- :books: Replaced some of the badges in the Readme file. [#721](https://github.com/PHPCompatibility/PHPCompatibility/pull/721), [#722](https://github.com/PHPCompatibility/PHPCompatibility/pull/722) +- :books: Composer: updated the list of package authors. [#739](https://github.com/PHPCompatibility/PHPCompatibility/pull/739) + +### Removed +- :no_entry_sign: Support for PHP_CodeSniffer 1.x and low 2.x versions. The new minimum version of PHP_CodeSniffer to be able to use this library is 2.3.0. [#699](https://github.com/PHPCompatibility/PHPCompatibility/pull/699). Fixes [#691](https://github.com/PHPCompatibility/PHPCompatibility/issues/691). + The minimum _recommended_ version of PHP_CodeSniffer remains the same, i.e. 2.6.0. +- :no_entry_sign: The `\PHPCompatibility\Sniff::inUseScope()` method has been removed as it is no longer needed now support for PHPCS 1.x has been dropped. [#699](https://github.com/PHPCompatibility/PHPCompatibility/pull/699) +- :no_entry_sign: Composer: The `autoload` section has been removed from the `composer.json` file. [#738](https://github.com/PHPCompatibility/PHPCompatibility/pull/738). Fixes [#568](https://github.com/PHPCompatibility/PHPCompatibility/issues/568). + Autoloading for this library is done via the PHP_CodeSniffer default mechanism, enhanced with our own autoloader, so the Composer autoloader shouldn't be needed and was causing issues in a particular use-case. + +### Fixed +- :bug: `PHPCompatibility.FunctionUse.NewFunctionParameters` sniff: The new `$mode` parameter of the `php_uname()` function was added in PHP 4.3, not in PHP 7.0 as was previously being reported. + The previous implementation of this check was based on an error in the PHP documentation. The error in the PHP documentation has been rectified and the sniff has followed suit. [#711](https://github.com/PHPCompatibility/PHPCompatibility/pull/711) +- :bug: `PHPCompatibility.Generators.NewGeneratorReturn` sniff: The sniff would throw false positives for `return` statements in nested constructs and did not correctly detect the scope which should be examined. [#725](https://github.com/PHPCompatibility/PHPCompatibility/pull/725). Fixes [#724](https://github.com/PHPCompatibility/PHPCompatibility/pull/724). +- :bug: `PHPCompatibility.Keywords.NewKeywords` sniff: PHP magic constants are case _in_sensitive. This sniff now accounts for this. [#707](https://github.com/PHPCompatibility/PHPCompatibility/pull/707) +- :bug: Various bugs in the `PHPCompatibility.Syntax.ForbiddenCallTimePassByReference` sniff [#723](https://github.com/PHPCompatibility/PHPCompatibility/pull/723): + - Closures called via a variable will now also be examined. (false negative) + - References within arrays/closures passed as function call parameters would incorrectly trigger an error. (false positive) +- :green_heart: Compatibility with PHPUnit 7.2. [#712](https://github.com/PHPCompatibility/PHPCompatibility/pull/712) + +### Credits +Thanks go out to [Jonathan Champ] for his contribution to this version. :clap: + + +## [8.2.0] - 2018-07-17 + +See all related issues and PRs in the [8.2.0 milestone]. + +### Important changes + +#### The repository has moved +As of July 13 2018, the PHPCompatibility repository has moved from the personal account of Wim Godden `wimg` to its own organization `PHPCompatibility`. +Composer users are advised to update their `composer.json`. The dependency is now called `phpcompatibility/php-compatibility`. + +#### Framework/CMS specific PHPCompatibility rulesets +Within this new organization, hosting will be offered for framework/CMS specific PHPCompatibility rulesets. + +The first two such repositories have been created and are now available for use: +* PHPCompatibilityJoomla [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityJoomla)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-joomla) +* PHPCompatibilityWP [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityWP)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) + +If you want to make sure you have all PHPCompatibility rulesets available at any time, you can use the PHPCompatibilityAll package [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityAll)|[Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-all). + +For more information, see the [Readme](https://github.com/PHPCompatibility/PHPCompatibility#using-a-frameworkcms-specific-ruleset) and [Contributing guidelines](https://github.com/PHPCompatibility/PHPCompatibility/blob/master/.github/CONTRIBUTING.md#frameworkcms-specific-rulesets). + +#### Changes expected in PHPCompatibility 9.0.0 +The next version of PHPCompatibility will include a major directory layout restructuring which means that the sniff codes of all sniffs will change. + +In this same release, support for PHP_CodeSniffer 1.5.x will be dropped. The new minimum supported PHPCS version will be 2.3.0. + +For more information about these upcoming changes, please read the [announcement](https://github.com/PHPCompatibility/PHPCompatibility/issues/688). + +The `9.0.0` release is expected to be ready later this summer. + + +### Added +- :star2: New `ArgumentFunctionsUsage` sniff to detect usage of the `func_get_args()`, `func_get_arg()` and `func_num_args()` functions and the changes regarding these functions introduced in PHP 5.3. [#596](https://github.com/PHPCompatibility/PHPCompatibility/pull/596). Fixes [#372](https://github.com/PHPCompatibility/PHPCompatibility/issues/372). +- :star2: New `DiscouragedSwitchContinue` sniff to detect `continue` targetting a `switch` control structure for which `E_WARNINGS` will be thrown as of PHP 7.3. [#687](https://github.com/PHPCompatibility/PHPCompatibility/pull/687) +- :star2: New `NewClassMemberAccess` sniff to detect class member access on instantiation as added in PHP 5.4 and class member access on cloning as added in PHP 7.0. [#619](https://github.com/PHPCompatibility/PHPCompatibility/pull/619). Fixes [#53](https://github.com/PHPCompatibility/PHPCompatibility/issues/53). +- :star2: New `NewConstantScalarExpressions` sniff to detect PHP 5.6 scalar expression in contexts where PHP previously only allowed static values. [#617](https://github.com/PHPCompatibility/PHPCompatibility/pull/617). Fixes [#399](https://github.com/PHPCompatibility/PHPCompatibility/issues/399). +- :star2: New `NewGeneratorReturn` sniff to detect `return` statements within generators as introduced in PHP 7.0. [#618](https://github.com/PHPCompatibility/PHPCompatibility/pull/618) +- :star2: New `PCRENewModifiers` sniff to initially detect the new `J` regex modifier as introduced in PHP 7.2. [#600](https://github.com/PHPCompatibility/PHPCompatibility/pull/600). Fixes [#556](https://github.com/PHPCompatibility/PHPCompatibility/issues/556). +- :star2: New `ReservedFunctionNames` sniff to report on double underscore prefixed functions and methods. This was previously reported via an upstream sniff. [#581](https://github.com/PHPCompatibility/PHPCompatibility/pull/581) +- :star2: New `NewTrailingComma` sniff to detect trailing comma's in function calls, method calls, `isset()` and `unset()` as will be introduced in PHP 7.3. [#632](https://github.com/PHPCompatibility/PHPCompatibility/pull/632) +- :star2: New `Upgrade/LowPHPCS` sniff to give users of old PHP_CodeSniffer versions advance warning when support will be dropped in the near future. [#693](https://github.com/PHPCompatibility/PHPCompatibility/pull/693) +- :star: `NewClasses` sniff: check for some 40+ additional PHP native classes added in various PHP versions. [#573](https://github.com/PHPCompatibility/PHPCompatibility/pull/573) +- :star: `NewClosure` sniff: check for usage of `self`/`parent`/`static::` being used within closures, support for which was only added in PHP 5.4. [#669](https://github.com/PHPCompatibility/PHPCompatibility/pull/669). Fixes [#668](https://github.com/PHPCompatibility/PHPCompatibility/pull/668). +- :star: `NewConstants` sniff: recognize constants added by the PHP 5.5+ password extension. [#626](https://github.com/PHPCompatibility/PHPCompatibility/pull/626) +- :star: `NewFunctionParameters` sniff: recognize a number of additional function parameters added in PHP 7.0, 7.1 and 7.2. [#602](https://github.com/PHPCompatibility/PHPCompatibility/pull/602) +- :star: `NewFunctions` sniff: recognize the PHP 5.1 SPL extension functions, the PHP 5.1.1 `hash_hmac()` function, the PHP 5.6 `pg_lo_truncate()` function, more PHP 7.2 Sodium functions and the new PHP 7.3 `is_countable()` function. [#606](https://github.com/PHPCompatibility/PHPCompatibility/pull/606), [#625](https://github.com/PHPCompatibility/PHPCompatibility/pull/625), [#640](https://github.com/PHPCompatibility/PHPCompatibility/pull/640), [#651](https://github.com/PHPCompatibility/PHPCompatibility/pull/651) +- :star: `NewHashAlgorithms` sniff: recognize the new hash algorithms which were added in PHP 7.1. [#599](https://github.com/PHPCompatibility/PHPCompatibility/pull/599) +- :star: `NewInterfaces` sniff: check for the PHP 5.0 `Reflector` interface. [#572](https://github.com/PHPCompatibility/PHPCompatibility/pull/572) +- :star: `OptionalRequiredFunctionParameters` sniff: detect missing `$salt` parameter in calls to the `crypt()` function (PHP 5.6+). [#605](https://github.com/PHPCompatibility/PHPCompatibility/pull/605) +- :star: `RequiredOptionalFunctionParameters` sniff: recognize that the `$varname` parameter of `getenv()` and the `$scale` parameter of `bcscale()` have become optional as of PHP 7.1 and 7.3 respectively. [#598](https://github.com/PHPCompatibility/PHPCompatibility/pull/598), [#612](https://github.com/PHPCompatibility/PHPCompatibility/pull/612) +- :star: New `AbstractFunctionCallParameterSniff` to be used as a basis for sniffs examining function call parameters. [#636](https://github.com/PHPCompatibility/PHPCompatibility/pull/636) +- :star: New `getReturnTypeHintName()` utility method to the `PHPCompatibility\Sniff` class. [#578](https://github.com/PHPCompatibility/PHPCompatibility/pull/578), [#642](https://github.com/PHPCompatibility/PHPCompatibility/pull/642) +- :star: New `isNumber()`, `isPositiveNumber()` and `isNegativeNumber()` utility methods to the `PHPCompatibility\Sniff` class. [#610](https://github.com/PHPCompatibility/PHPCompatibility/pull/610), [#650](https://github.com/PHPCompatibility/PHPCompatibility/pull/650) +- :star: New `isShortList()` utility method to the `PHPCompatibility\Sniff` class. [#635](https://github.com/PHPCompatibility/PHPCompatibility/pull/635) +- :star: New `getCommandLineData()` method to the `PHPCompatibility\PHPCSHelper` class to provide PHPCS cross-version compatible access to command line info at run time. [#693](https://github.com/PHPCompatibility/PHPCompatibility/pull/693) +- :star: Duplicate of upstream `findEndOfStatement()` method to the `PHPCompatibility\PHPCSHelper` class to allow for PHPCS cross-version usage of that method. [#614](https://github.com/PHPCompatibility/PHPCompatibility/pull/614) +- :umbrella: additional unit test to confirm that the `PHPCompatibility\Sniff::isUseOfGlobalConstant()` method handles multi-constant declarations correctly. [#587](https://github.com/PHPCompatibility/PHPCompatibility/pull/587) +- :umbrella: additional unit tests to confirm that the `PHPCompatibility\Sniff::isClassProperty()` method handles multi-property declarations correctly. [#583](https://github.com/PHPCompatibility/PHPCompatibility/pull/583) +- :books: [Readme](https://github.com/PHPCompatibility/PHPCompatibility#using-a-frameworkcms-specific-ruleset) & [Contributing](https://github.com/PHPCompatibility/PHPCompatibility/blob/master/.github/CONTRIBUTING.md#frameworkcms-specific-rulesets): add information about the framework/CMS specific rulesets. Related PRs: [#615](https://github.com/PHPCompatibility/PHPCompatibility/pull/615), [#624](https://github.com/PHPCompatibility/PHPCompatibility/pull/624), [#648](https://github.com/PHPCompatibility/PHPCompatibility/pull/648), [#674](https://github.com/PHPCompatibility/PHPCompatibility/pull/674), [#685](https://github.com/PHPCompatibility/PHPCompatibility/pull/685), [#694](https://github.com/PHPCompatibility/PHPCompatibility/pull/694). Related to issue [#530](https://github.com/PHPCompatibility/PHPCompatibility/issues/530). +- :books: Readme: information about the PHPCS 3.3.0 change which allows for a `testVersion` in a custom ruleset to be overruled by the command-line. [#607](https://github.com/PHPCompatibility/PHPCompatibility/pull/607) + +### Changed +- :books: Adjusted references to the old repository location throughout the codebase to reflect the move to a GitHub organization. [#689](https://github.com/PHPCompatibility/PHPCompatibility/pull/689) + This repository will now live in [https://github.com/PHPCompatibility/PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) and the Packagist reference will now be `phpcompatibility/php-compatibility`. +- :white_check_mark: The `getReturnTypeHintToken()` utility method has been made compatible with the changes in the PHPCS tokenizer which were introduced in PHP_CodeSniffer 3.3.0. [#642](https://github.com/PHPCompatibility/PHPCompatibility/pull/642). Fixes [#639](https://github.com/PHPCompatibility/PHPCompatibility/issues/639). +- :pushpin: `ConstantArrayUsingConst`: improved handling of multi-constant declarations. [#593](https://github.com/PHPCompatibility/PHPCompatibility/pull/593) +- :pushpin: `NewHeredocInitialize`: improved handling of constant declarations using the `const` keyword. + The sniff will now also report on multi-declarations for variables, constants and class properties and on using heredoc as a function parameter default. [#641](https://github.com/PHPCompatibility/PHPCompatibility/pull/641) +- :pushpin: `ForbiddenEmptyListAssignment`: this sniff will now also report on empty list assignments when the PHP 7.1 short list syntax is used. [#653](https://github.com/PHPCompatibility/PHPCompatibility/pull/653) +- :pushpin: The `ForbiddenNegativeBitshift` sniff would previously only report on "bitshift right". As of this version, "bitshift left" and bitshift assignments will also be recognized. [#614](https://github.com/PHPCompatibility/PHPCompatibility/pull/614) +- :pushpin: The `NewClasses` and `NewInterfaces` sniffs will now also report on new classes/interfaces when used as _return type_ declarations. [#578](https://github.com/PHPCompatibility/PHPCompatibility/pull/578) +- :pushpin: The `NewScalarTypeDeclarations` sniff will now recognize `parent` as a valid type declaration. + The sniff will now also throw an error about using `self` and `parent` when PHP < 5.2 needs to be supported as PHP 5.1 and lower would presume these to be class names instead of keywords. [#595](https://github.com/PHPCompatibility/PHPCompatibility/pull/595) +- :pushpin: The `PregReplaceEModifier` sniff - and the `PCRENewModifiers` sniff by extension - will now correctly examine and report on modifiers in regexes passed via calls to `preg_replace_callback_array()`. [#600](https://github.com/PHPCompatibility/PHPCompatibility/pull/600), [#636](https://github.com/PHPCompatibility/PHPCompatibility/pull/636) +- :pushpin: `getReturnTypeHintToken()` utility method: improved support for interface methods and abstract function declarations. [#652](https://github.com/PHPCompatibility/PHPCompatibility/pull/652) +- :pushpin: The `findExtendedClassName()`, `findImplementedInterfaceNames()`, `getMethodParameters()` utility methods which are duplicates of upstream PHPCS methods, have been moved from the `PHPCompatibility\Sniff` class to the `PHPCompatibility\PHPCSHelper` class and have become static methods. [#613](https://github.com/PHPCompatibility/PHPCompatibility/pull/613) +- :white_check_mark: `getReturnTypeHintToken()` utility method: align returned `$stackPtr` with native PHPCS behaviour by returning the last token of the type declaration. [#575](https://github.com/PHPCompatibility/PHPCompatibility/pull/575) +- :white_check_mark: PHPCS cross-version compatibility: sync `getMethodParameters()` method with improved upstream version. [#643](https://github.com/PHPCompatibility/PHPCompatibility/pull/643) +- :pencil2: The `MbstringReplaceEModifier`, `PregReplaceEModifier` and the `PregReplaceEModifier` sniffs now `extend` the new `AbstractFunctionCallParameterSniff` class. This should yield more accurate results when checking whether one of the target PHP functions was called. [#636](https://github.com/PHPCompatibility/PHPCompatibility/pull/636) +- :pencil2: `DeprecatedNewReference` sniff: minor change to the error text and code - was `Forbidden`, now `Removed` -. Custom rulesets which explicitly excluded this error code will need to be updated. [#594](https://github.com/PHPCompatibility/PHPCompatibility/pull/594) +- :pencil2: `NewScalarTypeDeclarations` sniff: minor change to the error message text.[#644](https://github.com/PHPCompatibility/PHPCompatibility/pull/644) +- :umbrella: The unit test framework now allows for sniffs in categories other than `PHP`. [#634](https://github.com/PHPCompatibility/PHPCompatibility/pull/634) +- :umbrella: Boyscouting: fixed up some (non-relevant) parse errors in a unit test case file. [#576](https://github.com/PHPCompatibility/PHPCompatibility/pull/576) +- :green_heart: Travis: build tests are now also being run against the lowest supported PHPCS 3.x version. Previously only the highest supported PHPCS 3.x version was tested against. [#633](https://github.com/PHPCompatibility/PHPCompatibility/pull/633) +- :books: Readme: Improved Composer install instructions. [#690](https://github.com/PHPCompatibility/PHPCompatibility/pull/690) +- :books: Minor documentation fixes. [#672](https://github.com/PHPCompatibility/PHPCompatibility/pull/672) +- :wrench: Minor performance optimizations and code simplifications. [#592](https://github.com/PHPCompatibility/PHPCompatibility/pull/592), [#630](https://github.com/PHPCompatibility/PHPCompatibility/pull/630), [#671](https://github.com/PHPCompatibility/PHPCompatibility/pull/671) +- :wrench: Composer: Various improvements, including improved information about the suggested packages, suggesting `roave/security-advisories`, allowing for PHPUnit 7.x. [#604](https://github.com/PHPCompatibility/PHPCompatibility/pull/604/files), [#616](https://github.com/PHPCompatibility/PHPCompatibility/pull/616), [#622](https://github.com/PHPCompatibility/PHPCompatibility/pull/622), [#646](https://github.com/PHPCompatibility/PHPCompatibility/pull/646) +- :wrench: Various Travis build script improvements, including tweaks for faster build time, validation of the `composer.json` file, validation of the framework specific rulesets. [#570](https://github.com/PHPCompatibility/PHPCompatibility/pull/570), [#571](https://github.com/PHPCompatibility/PHPCompatibility/pull/571), [#579](https://github.com/PHPCompatibility/PHPCompatibility/pull/579), [#621](https://github.com/PHPCompatibility/PHPCompatibility/pull/621), [#631](https://github.com/PHPCompatibility/PHPCompatibility/pull/631) +- :wrench: Build/PHPCS: made some more CS conventions explicit and start using PHPCS 3.x options for the PHPCompatibility native ruleset. [#586](https://github.com/PHPCompatibility/PHPCompatibility/pull/586), [#667](https://github.com/PHPCompatibility/PHPCompatibility/pull/667), [#673](https://github.com/PHPCompatibility/PHPCompatibility/pull/673) +- :wrench: Some code style clean up and start using the new inline PHPCS 3.2+ annotations where applicable. [#586](https://github.com/PHPCompatibility/PHPCompatibility/pull/586), [#591](https://github.com/PHPCompatibility/PHPCompatibility/pull/591), [#620](https://github.com/PHPCompatibility/PHPCompatibility/pull/620), [#673](https://github.com/PHPCompatibility/PHPCompatibility/pull/673) + +### Removed +- :no_entry_sign: PHPCompatibility no longer explicitly supports PHP_CodeSniffer 2.2.0. [#687](https://github.com/PHPCompatibility/PHPCompatibility/pull/687), [#690](https://github.com/PHPCompatibility/PHPCompatibility/pull/690) +- :no_entry_sign: The PHPCompatibility ruleset no longer includes the PHPCS native `Generic.NamingConventions.CamelCapsFunctionName`. Double underscore prefixed function names are now being reported on by a new dedicated sniff. [#581](https://github.com/PHPCompatibility/PHPCompatibility/pull/581) +- :no_entry_sign: PHPCompatibility no longer explicitly supports HHVM and builds are no longer tested against HHVM. + For now, running PHPCompatibility on HHVM to test PHP code may still work for a little while, but HHVM has announced they are [dropping PHP support](https://hhvm.com/blog/2017/09/18/the-future-of-hhvm.html). [#623](https://github.com/PHPCompatibility/PHPCompatibility/pull/623). Fixes [#603](https://github.com/PHPCompatibility/PHPCompatibility/issues/603). +- :books: Readme: badges from services which are no longer supported or inaccurate. [#609](https://github.com/PHPCompatibility/PHPCompatibility/pull/609), [#628](https://github.com/PHPCompatibility/PHPCompatibility/pull/628) + +### Fixed +- :bug: Previously, the PHPCS native `Generic.NamingConventions.CamelCapsFunctionName` sniff was included in PHPCompatibility. Some error codes of this sniff were excluded, as well as some error messages changed (via the ruleset). + If/when PHPCompatibility would be used in combination with a code style-type ruleset, this could inadvertently lead to underreporting of issues which the CS-type ruleset intends to have reported - i.e. the error codes excluded by PHPCompatibility -. This has now been fixed. [#581](https://github.com/PHPCompatibility/PHPCompatibility/pull/581) +- :bug: The `ForbiddenNegativeBitshift` sniff would incorrectly throw an error when a bitshift was based on a calculation which included a negative number, but would not necessarily result in a negative number. [#614](https://github.com/PHPCompatibility/PHPCompatibility/pull/614). Fixes [#294](https://github.com/PHPCompatibility/PHPCompatibility/issues/294), [#466](https://github.com/PHPCompatibility/PHPCompatibility/issues/466). +- :bug: The `NewClosure` sniff would report the same issue twice when the issue was encountered in a nested closure. [#669](https://github.com/PHPCompatibility/PHPCompatibility/pull/669) +- :bug: The `NewKeywords` sniff would underreport on non-lowercase keywords. [#627](https://github.com/PHPCompatibility/PHPCompatibility/pull/627) +- :bug: The `NewKeywords` sniff would incorrectly report on the use of class constants and class properties using the same name as a keyword. [#627](https://github.com/PHPCompatibility/PHPCompatibility/pull/627) +- :bug: The `NewNullableTypes` sniff would potentially underreport when comments where interspersed in the (return) type declarations. [#577](https://github.com/PHPCompatibility/PHPCompatibility/pull/577) +- :bug: The `Sniff::getFunctionCallParameters()` utility method would in rare cases return incorrect results when it encountered a closure as a parameter. [#682](https://github.com/PHPCompatibility/PHPCompatibility/pull/682) +- :bug: The `Sniff::getReturnTypeHintToken()` utility method would not always return a `$stackPtr`. [#645](https://github.com/PHPCompatibility/PHPCompatibility/pull/645) +- :bug: Minor miscellanous other bugfixes. [#670](https://github.com/PHPCompatibility/PHPCompatibility/pull/670) +- :umbrella: `PHPCompatibility\Tests\BaseClass\MethodTestFrame::getTargetToken()` could potentially not find the correct token to run a test against. [#588](https://github.com/PHPCompatibility/PHPCompatibility/pull/588) + +### Credits +Thanks go out to [Michael Babker] and [Juliette Reinders Folmer] for their contributions to this version. :clap: + + +## [8.1.0] - 2017-12-27 + +See all related issues and PRs in the [8.1.0 milestone]. + +### Added +- :star2: New `NewConstants` and `RemovedConstants` sniffs to detect usage of new/removed PHP constants for all PHP versions from PHP 5 up. [#526](https://github.com/PHPCompatibility/PHPCompatibility/pull/525), [#551](https://github.com/PHPCompatibility/PHPCompatibility/pull/551), [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566). Fixes [#263](https://github.com/PHPCompatibility/PHPCompatibility/issues/263). +- :star2: New `MagicAutoloadDeprecation` sniff to detect deprecated `__autoload()` functions as deprecated in PHP 7.2. [#540](https://github.com/PHPCompatibility/PHPCompatibility/pull/540) +- :star2: New `OptionalRequiredFunctionParameter` sniff to check for missing function call parameters which were required and only became optional in a later PHP version. [#524](https://github.com/PHPCompatibility/PHPCompatibility/pull/524) +- :star2: New `DynamicAccessToStatic` sniff to detect dynamic access to static methods and properties, as well as class constants, prior to PHP 5.3. [#535](https://github.com/PHPCompatibility/PHPCompatibility/pull/535). Fixes [#534](https://github.com/PHPCompatibility/PHPCompatibility/issues/534). +- :star: `DeprecatedFunctions` sniff: recognize yet more PHP 7.2 deprecated functions. [#561](https://github.com/PHPCompatibility/PHPCompatibility/pull/561), [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566) +- :star: `DeprecatedIniDirectives` sniff: recognize the last of the PHP 7.2 deprecated ini directives. [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566), [#567](https://github.com/PHPCompatibility/PHPCompatibility/pull/567) +- :star: `NewFunctions` : detection of all new PHP 7.2 functions added. [#522](https://github.com/PHPCompatibility/PHPCompatibility/pull/522), [#545](https://github.com/PHPCompatibility/PHPCompatibility/pull/545), [#551](https://github.com/PHPCompatibility/PHPCompatibility/pull/551), [#565](https://github.com/PHPCompatibility/PHPCompatibility/pull/565) +- :star: `RemovedExtensions` : report on usage of the `mcrypt` extension which has been removed in PHP 7.2. [#566](https://github.com/PHPCompatibility/PHPCompatibility/pull/566) +- :star: `RemovedGlobalVariables` : detection of the use of `$php_errormsg` with `track_errors` which has been deprecated in PHP 7.2. [#528](https://github.com/PHPCompatibility/PHPCompatibility/pull/528) +- :books: Documentation : added reporting usage instructions. [#533](https://github.com/PHPCompatibility/PHPCompatibility/pull/533), [#552](https://github.com/PHPCompatibility/PHPCompatibility/pull/552) + +### Changed +- :pushpin: `NewClosures` : downgraded "$this found in closure outside class" to warning. [#536](https://github.com/PHPCompatibility/PHPCompatibility/pull/535). Fixes [#527](https://github.com/PHPCompatibility/PHPCompatibility/issues/527). +- :pushpin: `ForbiddenGlobalVariableVariable` : the sniff will now throw an error for each variable in a `global` statement which is no longer supported and show the variable found to make it easier to fix this. Previously only one error would be thrown per `global` statement. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564) +- :pushpin: `ForbiddenGlobalVariableVariable` : the sniff will now throw `warning`s for non-bare variables used in a `global` statement as those are discouraged since PHP 7.0. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564) +- :rewind: `NewLanguageConstructs` : updated the version number for `T_COALESCE_EQUAL`. [#523](https://github.com/PHPCompatibility/PHPCompatibility/pull/523) +- :pencil2: `Sniff::getTestVersion()` : simplified regex logic. [#520](https://github.com/PHPCompatibility/PHPCompatibility/pull/520) +- :green_heart: Travis : build tests are now being run against PHP 7.2 as well. [#511](https://github.com/PHPCompatibility/PHPCompatibility/pull/511) +- :wrench: Improved check for superfluous whitespaces in files. [#542](https://github.com/PHPCompatibility/PHPCompatibility/pull/542) +- :wrench: Build/PHPCS : stabilized the exclude patterns. [#529](https://github.com/PHPCompatibility/PHPCompatibility/pull/529) +- :wrench: Build/PHPCS : added array indentation check. [#538](https://github.com/PHPCompatibility/PHPCompatibility/pull/538) +- :white_check_mark: PHPCS cross-version compatibility : sync `FindExtendedClassname()` method with upstream. [#507](https://github.com/PHPCompatibility/PHPCompatibility/pull/507) +- :wrench: The minimum version for the recommended `DealerDirect/phpcodesniffer-composer-installer` Composer plugin has been upped to `0.4.3`. [#548](https://github.com/PHPCompatibility/PHPCompatibility/pull/548) + +### Fixed +- :bug: `ForbiddenCallTimePassByReference` : a false positive was being thrown when a global constant was followed by a _bitwise and_. [#562](https://github.com/PHPCompatibility/PHPCompatibility/pull/562). Fixes [#39](https://github.com/PHPCompatibility/PHPCompatibility/issues/39). +- :bug: `ForbiddenGlobalVariableVariable` : the sniff was overzealous and would also report on `global` in combination with variable variables which are still supported. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564). Fixes [#537](https://github.com/PHPCompatibility/PHPCompatibility/issues/537). +- :bug: `ForbiddenGlobalVariableVariable` : variables interspersed with whitespace and/or comments were not being reported. [#564](https://github.com/PHPCompatibility/PHPCompatibility/pull/564) +- :rewind: `ForbiddenNamesAsInvokedFunctions` : improved recognition of function invocations using forbidden words and prevent warnings for keywords which are no longer forbidden as method names in PHP 7.0+. [#516](https://github.com/PHPCompatibility/PHPCompatibility/pull/516). Fixes [#515](https://github.com/PHPCompatibility/PHPCompatibility/issues/515) +- :bug: `VariableVariables` : variables interspersed with whitespace and/or comments were not being reported. [#563](https://github.com/PHPCompatibility/PHPCompatibility/pull/563) +- :umbrella: Fixed some unintentional syntax errors in test files. [#539](https://github.com/PHPCompatibility/PHPCompatibility/pull/539) +- :umbrella: Tests : fixed case numbering error. [#525](https://github.com/PHPCompatibility/PHPCompatibility/pull/525) +- :books: Tests : added missing test skip explanation. [#521](https://github.com/PHPCompatibility/PHPCompatibility/pull/521) +- :wrench: Fixed PHPCS whitespaces. [#543](https://github.com/PHPCompatibility/PHPCompatibility/pull/543) +- :wrench: Fixed code test coverage verification. [#550](https://github.com/PHPCompatibility/PHPCompatibility/pull/550). Fixes [#549](https://github.com/PHPCompatibility/PHPCompatibility/issues/549). + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Jonathan Van Belle] for their contributions to this version. :clap: + + +## [8.0.1] - 2017-08-07 + +See all related issues and PRs in the [8.0.1 milestone]. + +### Added +- :star2: New `DeprecatedTypeCasts` sniff to detect deprecated and removed type casts, such as the `(unset)` type cast as deprecated in PHP 7.2. [#498](https://github.com/PHPCompatibility/PHPCompatibility/pull/498) +- :star2: New `NewTypeCasts` sniff to detect type casts not present in older PHP versions such as the `(binary)` type cast as added in PHP 5.2.1. [#497](https://github.com/PHPCompatibility/PHPCompatibility/pull/497) +- :star: `NewGroupUseDeclaration`: Detection of PHP 7.2 trailing comma's in group use statements. [#504](https://github.com/PHPCompatibility/PHPCompatibility/pull/504) +- :star: `DeprecatedFunctions` sniff: recognize some more PHP 7.2 deprecated functions. [#501](https://github.com/PHPCompatibility/PHPCompatibility/pull/501) +- :star: `DeprecatedIniDirectives` sniff: recognize more PHP 7.2 deprecated ini directives. [#500](https://github.com/PHPCompatibility/PHPCompatibility/pull/500) +- :star: `ForbiddenNames` sniff: recognize `object` as a forbidden keyword since PHP 7.2. [#499](https://github.com/PHPCompatibility/PHPCompatibility/pull/499) +- :star: `NewReturnTypeDeclarations` sniff: recognize generic `parent`, PHP 7.1 `iterable` and PHP 7.2 `object` return type declarations. [#505](https://github.com/PHPCompatibility/PHPCompatibility/pull/505), [#499](https://github.com/PHPCompatibility/PHPCompatibility/pull/499) +- :star: `NewScalarTypeDeclarations` sniff: recognize PHP 7.2 `object` type declarion. [#499](https://github.com/PHPCompatibility/PHPCompatibility/pull/499) + +### Changed +- :pencil2: Improved clarity of the deprecated functions alternative in the error message. [#502](https://github.com/PHPCompatibility/PHPCompatibility/pull/502) + +### Fixed +- :fire_engine: Temporary hotfix for installed_paths (pending [upstream fix](https://github.com/squizlabs/PHP_CodeSniffer/issues/1591).) [#503](https://github.com/PHPCompatibility/PHPCompatibility/pull/503) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + + +## [8.0.0] - 2017-08-03 + +**IMPORTANT**: This release contains a **breaking change**. Please read the below information carefully before upgrading! + +The directory layout of the PHPCompatibility standard has been changed for improved compatibility with Composer. +This means that the PHPCompatibility standard no longer extends from the root directory of the repository, but now lives in its own subdirectory `/PHPCompatibility`. + +This release also bring compatibility with PHPCS 3.x to the PHPCompatibility standard. + +There are two things you will need to be aware of: +* The path to the PHPCompatibility standard has changed. +* If you intend to upgrade to PHPCS 3.x, the path to the `phpcs` script has changed (upstream change). + +Please follow the below upgrade instructions carefully. This should be a one-time only action. + +### Upgrade instructions + +### Before upgrading + +If you had previously made accommodations for the old directory layout, you should remove any such _"hacks"_ (meant in the kindest of ways) now. + +By this we mean: symlinks for the PHPCompatibility install to the `PHP_CodeSniffer/CodeSniffer/Standards` directory, scripts to move the sniffs files to the PHPCS directory, scripts which made symlinks etc. + +So, please remove those first. + +> **Side-note**: +> +> If you had previously forked this repository to solve this issue, please consider reverting your fork to the official version or removing it all together. + +### Upgrading: re-registering PHPCompatibility with PHP CodeSniffer + +External PHP CodeSniffer standards need to be registered with PHP CodeSniffer. You have probably done this the first time you used PHPCompatibility or have a script or Composer plugin in place to do this for you. + +As the directory layout of PHPCompatibility has changed, the path previously registered with PHP CodeSniffer will no longer work and running `phpcs -i` will **_not_** list PHPCompatibility as one of the registered standards. + +#### Using a Composer plugin + +If you use Composer, we recommend you use a Composer plugin to sort this out. In previous install instructions we recommended the SimplyAdmin plugin for this. This plugin has since been abandoned. We now recommend the DealerDirect plugin. +```bash +composer remove --dev simplyadmire/composer-plugins +composer require --dev dealerdirect/phpcodesniffer-composer-installer:^0.4.3 +composer install +composer update phpcompatibility/php-compatibility squizlabs/php_codesniffer +vendor/bin/phpcs -i +``` +If all went well, you should now see PHPCompatibility listed again in the list of installed standards. + +#### Manually re-registering PHPCompatibility + +1. First run `phpcs --config-show` to check which path(s) are currently registered with PHP CodeSniffer for external standards. +2. Check in the below table what the new path for PHPCompatibility will be - the path should point to the root directory of your PHPCompatibility install (not to the sub-directory of the same name): + + Install type | Old path | New path + ------------ | -------- | --------- + Composer | `vendor/wimg` | `vendor/phpcompatibility/php-compatibility` + Unzipped release to arbitrary directory | `path/to/dir/abovePHPCompatibility` | `path/to/dir/abovePHPCompatibility/PHPCompatibility` + Git checkout | `path/to/dir/abovePHPCompatibility` | `path/to/dir/abovePHPCompatibility/PHPCompatibility` + PEAR | If the old install instruction has been followed, not registered. | `path/to/PHPCompatibility` + + > **Side-note**: + > + > If you used the old install instructions for a PEAR install, i.e. checking out the latest release to the `PHP/CodeSniffer/Standards/PHPCompatibility` directory, and you intend to upgrade to PHP CodeSniffer 3.x, it is recommended you move the PHPCompatibility folder out of the PEAR directory now, as the layout of the PHPCS directory has changed with PHPCS 3.x and you may otherwise lose your PHPCompatibility install when you upgrade PHP CodeSniffer via PEAR. + +3. There are two ways in which you can register the new `installed_paths` value with PHP CodeSniffer. Choose your preferred method: + * Run `phpcs --config-set installed_paths ...` and include all previously installed paths including the _adjusted_ path for the PHPCompatibility standard. + + For example, if the previous value of `installed_paths` was + + `/path/to/MyStandard,/path/to/dir/abovePHPCompatibility` + + you should now set it using + + `phpcs --config-set installed_paths /path/to/MyStandard,/path/to/PHPCompatibility` + + * If you use a custom ruleset in combination with PHPCS 2.6.0 or higher, you can pass the value to PHPCS from your custom ruleset: + ```xml + + ``` +4. Run `phpcs -i` to verify that the PHPCompatibility standard is now listed again in the list of installed standards. + + +### Upgrading to PHPCS 3.x + +The path to the `phpcs` script has changed in PHPCS 3.x which will impact how you call PHPCS. + +Version | PHPCS 2.x | PHPCS 3.x +------- | --------- | --------- +Generic `phpcs` Command | `path/to/PHP_CodeSniffer/scripts/phpcs ....` | `path/to/PHP_CodeSniffer/bin/phpcs ....` +Composer command | `vendor/bin/phpcs ...` | `vendor/bin/phpcs ...` + +So, for Composer users, nothing changes. For everyone else, you may want to add the `path/to/PHP_CodeSniffer/bin/phpcs` path to your PATH environment variable or adjust any scripts - like build scripts - which call PHPCS. + + +### Upgrading a Travis build script + +If you run PHPCompatibility against your code as part of your Travis build: +* If you use Composer to install PHP CodeSniffer and PHPCompatibility on the travis image and you've made the above mentioned changes, your build should pass again. +* If you use `git clone` to install PHP CodeSniffer and PHPCompatibility on the travis image, your build will fail until you make the following changes: + 1. Check which branch of PHPCS is being checked out. If you previously fixed this to a pre-PHPCS 3.x branch or tag, you can now change this (back) to `master` or a PHPCS 3 tag. + 2. Check to which path PHPCompatibility is being cloned and adjust the path if necessary. + 3. Adjust the `phpcs --config-set installed_paths` command as described above to point to the root of the cloned PHPCompatibility repo. + 4. If you switched to using PHPCS 3.x, adjust the call to PHPCS. + + + +### Changelog for version 8.0.0 + +See all related issues and PRs in the [8.0.0 milestone]. + +### Added +- :two_hearts: Support for PHP CodeSniffer 3.x. [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482), [#481](https://github.com/PHPCompatibility/PHPCompatibility/pull/481), [#480](https://github.com/PHPCompatibility/PHPCompatibility/pull/480), [#488](https://github.com/PHPCompatibility/PHPCompatibility/pull/488), [#489](https://github.com/PHPCompatibility/PHPCompatibility/pull/489), [#495](https://github.com/PHPCompatibility/PHPCompatibility/pull/495) + +### Changed +- :gift: As of this version PHPCompatibility will use semantic versioning. +- :fire: The directory structure of the repository has changed for better compatibility with installation via Composer. [#446](https://github.com/PHPCompatibility/PHPCompatibility/pull/446). Fixes [#102](https://github.com/PHPCompatibility/PHPCompatibility/issues/102), [#107](https://github.com/PHPCompatibility/PHPCompatibility/issues/107) +- :pencil2: The custom `functionWhitelist` property for the `PHPCompatibility.PHP.RemovedExtensions` sniff is now only supported in combination with PHP CodeSniffer 2.6.0 or higher (due to an upstream bug which was fixed in PHPCS 2.6.0). [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482) +- :wrench: Improved the information provided to Composer from the `composer.json` file. [#446](https://github.com/PHPCompatibility/PHPCompatibility/pull/446), [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482), [#486](https://github.com/PHPCompatibility/PHPCompatibility/pull/486) +- :wrench: Release archives will no longer contain the unit tests and other typical development files. You can still get these by using Composer with `--prefer-source` or by checking out a git clone of the repository. [#494](https://github.com/PHPCompatibility/PHPCompatibility/pull/494) +- :wrench: A variety of minor improvements to the build process. [#485](https://github.com/PHPCompatibility/PHPCompatibility/pull/485), [#486](https://github.com/PHPCompatibility/PHPCompatibility/pull/486), [#487](https://github.com/PHPCompatibility/PHPCompatibility/pull/487) +- :wrench: Some files for use by contributors have been renamed to use `.dist` extensions or moved for easier access. [#478](https://github.com/PHPCompatibility/PHPCompatibility/pull/478), [#479](https://github.com/PHPCompatibility/PHPCompatibility/pull/479), [#483](https://github.com/PHPCompatibility/PHPCompatibility/pull/483), [#493](https://github.com/PHPCompatibility/PHPCompatibility/pull/493) +- :books: The installation instructions in the Readme. [#496](https://github.com/PHPCompatibility/PHPCompatibility/pull/496) +- :books: The unit test instructions in the Contributing file. [#496](https://github.com/PHPCompatibility/PHPCompatibility/pull/496) +- :books: Improved the example code in the Readme. [#490](https://github.com/PHPCompatibility/PHPCompatibility/pull/490) + +### Removed +- :no_entry_sign: Support for PHP 5.1 and 5.2. + + The sniffs can now only be run on PHP 5.3 or higher in combination with PHPCS 1.5.6 or 2.x and on PHP 5.4 or higher in combination with PHPCS 3.x. [#484](https://github.com/PHPCompatibility/PHPCompatibility/pull/484), [#482](https://github.com/PHPCompatibility/PHPCompatibility/pull/482) + +### Credits +Thanks go out to [Gary Jones] and [Juliette Reinders Folmer] for their contributions to this version. :clap: + + +## [7.1.5] - 2017-07-17 + +See all related issues and PRs in the [7.1.5 milestone]. + +### Added +- :star: The `NewKeywords` sniff will now also sniff for `yield from` which was introduced in PHP 7.0. [#477](https://github.com/PHPCompatibility/PHPCompatibility/pull/477). Fixes [#476](https://github.com/PHPCompatibility/PHPCompatibility/issues/476) +- :books: The LGPL-3.0 license. [#447](https://github.com/PHPCompatibility/PHPCompatibility/pull/447) + +### Changed +- :rewind: The `NewExecutionDirectives` sniff will now also report on execution directives when used in combination with PHPCS 2.0.0-2.3.3. [#451](https://github.com/PHPCompatibility/PHPCompatibility/pull/451) +- :rewind: The `getMethodParameters()` utility method will no longer break when used with PHPCS 1.5.x < 1.5.6. This affected a number of sniffs. [#452](https://github.com/PHPCompatibility/PHPCompatibility/pull/452) +- :rewind: The `inUseScope()` utility method will no longer break when used with PHPCS 2.0.0 - 2.2.0. This affected a number of sniffs. [#454](https://github.com/PHPCompatibility/PHPCompatibility/pull/454) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#443](https://github.com/PHPCompatibility/PHPCompatibility/pull/443), [#474](https://github.com/PHPCompatibility/PHPCompatibility/pull/474) +- :pencil2: Renamed a test file for consistency. [#453](https://github.com/PHPCompatibility/PHPCompatibility/pull/453) +- :wrench: Code style clean up. [#429](https://github.com/PHPCompatibility/PHPCompatibility/pull/429) +- :wrench: Prevent Composer installing PHPCS 3.x. **_PHPCS 3.x is not (yet) supported by the PHPCompatibility standard, but will be in the near future._** [#444](https://github.com/PHPCompatibility/PHPCompatibility/pull/444) +- :green_heart: The code base will now be checked for consistent code style during build testing. [#429](https://github.com/PHPCompatibility/PHPCompatibility/pull/429) +- :green_heart: The sniffs are now also tested against HHVM for consistent results. _Note: the sniffs do not contain any HHVM specific checks nor is there any intention to add them at this time._ [#450](https://github.com/PHPCompatibility/PHPCompatibility/pull/450) +- :books: Made it explicit that - at this moment - PHPCS 3.x is not (yet) supported. [#444](https://github.com/PHPCompatibility/PHPCompatibility/pull/444) +- :books: Minor improvements to the Readme. [#448](https://github.com/PHPCompatibility/PHPCompatibility/pull/448), [#449](https://github.com/PHPCompatibility/PHPCompatibility/pull/449), [#468](https://github.com/PHPCompatibility/PHPCompatibility/pull/468) +- :books: Minor improvements to the Contributing guidelines. [#467](https://github.com/PHPCompatibility/PHPCompatibility/pull/467) + +### Removed +- :no_entry_sign: The `DefaultTimeZoneRequired` sniff. This sniff was checking server settings rather than code. [#458](https://github.com/PHPCompatibility/PHPCompatibility/pull/458). Fixes [#457](https://github.com/PHPCompatibility/PHPCompatibility/issues/457) +- :no_entry_sign: The `NewMagicClassConstant` sniff as introduced in v 7.1.4 contained two additional checks for not strictly compatibility related issues. One of these was plainly wrong, the other opinionated. Both have been removed. [#442](https://github.com/PHPCompatibility/PHPCompatibility/pull/442). Fixes [#436](https://github.com/PHPCompatibility/PHPCompatibility/issues/436) + +### Fixed +- :bug: `NewClass` sniff: was reporting an incorrect introduction version number for a few of the Exception classes. [#441](https://github.com/PHPCompatibility/PHPCompatibility/pull/441). Fixes [#440](https://github.com/PHPCompatibility/PHPCompatibility/issues/440). +- :bug: `ForbiddenBreakContinueVariableArguments` sniff: was incorrectly reporting an error if the `break` or `continue` was followed by a PHP closing tag (breaking out of PHP). [#462](https://github.com/PHPCompatibility/PHPCompatibility/pull/462). Fixes [#460](https://github.com/PHPCompatibility/PHPCompatibility/issues/460) +- :bug: `ForbiddenGlobalVariableVariable` sniff: was incorrectly reporting an error if the `global` statement was followed by a PHP closing tag (breaking out of PHP). [#463](https://github.com/PHPCompatibility/PHPCompatibility/pull/463). +- :bug: `DeprecatedFunctions` sniff: was reporting false positives for classes using the same name as a deprecated function. [#465](https://github.com/PHPCompatibility/PHPCompatibility/pull/465). Fixes [#464](https://github.com/PHPCompatibility/PHPCompatibility/issues/464) + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Mark Clements] for their contributions to this version. :clap: + + +## [7.1.4] - 2017-05-06 + +See all related issues and PRs in the [7.1.4 milestone]. + +### Added +- :star2: New `CaseSensitiveKeywords` sniff to detect use of non-lowercase `self`, `static` and `parent` keywords which could cause compatibility issues pre-PHP 5.5. [#382](https://github.com/PHPCompatibility/PHPCompatibility/pull/382) +- :star2: New `ConstantArraysUsingConst` sniff to detect constants defined using the `const` keyword being assigned an array value which was not supported prior to PHP 5.6. [#397](https://github.com/PHPCompatibility/PHPCompatibility/pull/397) +- :star2: New `ForbiddenClosureUseVariableNames` sniff to detect PHP 7.1 forbidden variable names in closure use statements. [#386](https://github.com/PHPCompatibility/PHPCompatibility/pull/386). Fixes [#374](https://github.com/PHPCompatibility/PHPCompatibility/issues/374) +- :star2: New `NewArrayStringDereferencing` sniff to detect array and string literal dereferencing as introduced in PHP 5.5. [#388](https://github.com/PHPCompatibility/PHPCompatibility/pull/388) +- :star2: New `NewHeredocInitialize` sniff to detect initialization of static variables and class properties/constants using the heredoc syntax which is supported since PHP 5.3. [#391](https://github.com/PHPCompatibility/PHPCompatibility/pull/391). Fixes [#51](https://github.com/PHPCompatibility/PHPCompatibility/issues/51) +- :star2: New `NewMagicClassConstant` sniff to detect use of the magic `::class` constant as introduced in PHP 5.5. [#403](https://github.com/PHPCompatibility/PHPCompatibility/pull/403). Fixes [#364](https://github.com/PHPCompatibility/PHPCompatibility/issues/364). +- :star2: New `NewUseConstFunction` sniff to detect use statements importing constants and functions as introduced in PHP 5.6. [#401](https://github.com/PHPCompatibility/PHPCompatibility/pull/401) +- :star: `DeprecatedFunctions` sniff: recognize PHP 7.2 deprecated GD functions. [#392](https://github.com/PHPCompatibility/PHPCompatibility/pull/392) +- :star: `DeprecatedIniDirectives` sniff: recognize PHP 7.2 deprecated `mbstring.func_overload` directive. [#377](https://github.com/PHPCompatibility/PHPCompatibility/pull/377) +- :star: `NewClasses` sniff: check for the PHP 5.1 `libXMLError` class. [#412](https://github.com/PHPCompatibility/PHPCompatibility/pull/412) +- :star: `NewClasses` sniff: recognize all native PHP Exception classes. [#418](https://github.com/PHPCompatibility/PHPCompatibility/pull/418) +- :star: `NewClosure` sniff: check for closures being declared as static and closures using `$this`. Both of which was not supported pre-PHP 5.4. [#389](https://github.com/PHPCompatibility/PHPCompatibility/pull/389). Fixes [#24](https://github.com/PHPCompatibility/PHPCompatibility/issues/24). +- :star: `NewFunctionParameters` sniff: recognize new `exclude_disabled` parameter for the `get_defined_functions()` function as introduced in PHP 7.0.15. [#375](https://github.com/PHPCompatibility/PHPCompatibility/pull/375) +- :star: `NewFunctions` sniff: recognize new PHP 7.2 socket related functions. [#376](https://github.com/PHPCompatibility/PHPCompatibility/pull/376) +- :star: `NewInterfaces` sniff: check for some more PHP native interfaces. [#411](https://github.com/PHPCompatibility/PHPCompatibility/pull/411) +- :star: New `isClassProperty()`, `isClassConstant()` and `validDirectScope()` utility methods to the `PHPCompatibility_Sniff` class. [#393](https://github.com/PHPCompatibility/PHPCompatibility/pull/393), [#391](https://github.com/PHPCompatibility/PHPCompatibility/pull/391). +- :star: New `getTypeHintsFromFunctionDeclaration()` utility method to the `PHPCompatibility_Sniff` class. [#414](https://github.com/PHPCompatibility/PHPCompatibility/pull/414). +- :umbrella: Unit tests against false positives for the `NewMagicMethods` sniff. [#381](https://github.com/PHPCompatibility/PHPCompatibility/pull/381) +- :umbrella: More unit tests for the `getTestVersion()` utility method. [#405](https://github.com/PHPCompatibility/PHPCompatibility/pull/405), [#430](https://github.com/PHPCompatibility/PHPCompatibility/pull/430) +- :green_heart: The XML of the ruleset will now be validated and checked for consistent code style during the build testing by Travis. [#433](https://github.com/PHPCompatibility/PHPCompatibility/pull/433) +- :books: Readme: information about setting `installed_paths` via a custom ruleset. [#407](https://github.com/PHPCompatibility/PHPCompatibility/pull/407) +- :books: `Changelog.md` file containing a record of notable changes since the first tagged release. [#421](https://github.com/PHPCompatibility/PHPCompatibility/pull/421) + +### Changed +- :pushpin: The `ForbiddenNamesAsDeclared` sniff will now emit `warning`s for soft reserved keywords. [#406](https://github.com/PHPCompatibility/PHPCompatibility/pull/406), [#370](https://github.com/PHPCompatibility/PHPCompatibility/pull/370). +- :pushpin: The `ForbiddenNames` sniff will now allow for the more liberal rules for usage of reserved keywords as of PHP 7.0. [#417](https://github.com/PHPCompatibility/PHPCompatibility/pull/417) +- :pushpin: The `InternalInterfaces`, `NewClasses`, `NewConstVisibility`, `NewInterfaces`, `NewMagicMethods`, `NonStaticMagicMethods` and `RemovedGlobalVariables` sniffs will now also sniff for and correctly report violations in combination with anonymous classes. [#378](https://github.com/PHPCompatibility/PHPCompatibility/pull/378), [#383](https://github.com/PHPCompatibility/PHPCompatibility/pull/383), [#393](https://github.com/PHPCompatibility/PHPCompatibility/pull/393), [#394](https://github.com/PHPCompatibility/PHPCompatibility/pull/394), [#395](https://github.com/PHPCompatibility/PHPCompatibility/pull/395), [#396](https://github.com/PHPCompatibility/PHPCompatibility/pull/396). Fixes [#351](https://github.com/PHPCompatibility/PHPCompatibility/issues/351) and [#333](https://github.com/PHPCompatibility/PHPCompatibility/issues/333). +- :pushpin: The `NewClasses` and `NewInterfaces` sniffs will now also report on new classes/interfaces when used as type hints. [#414](https://github.com/PHPCompatibility/PHPCompatibility/pull/414), [#416](https://github.com/PHPCompatibility/PHPCompatibility/pull/416). Fixes [#352](https://github.com/PHPCompatibility/PHPCompatibility/issues/352) +- :pushpin: The `NewClasses` sniff will now also report on Exception classes when used in (multi-)`catch` statements. [#418](https://github.com/PHPCompatibility/PHPCompatibility/pull/418). Fixes [#373](https://github.com/PHPCompatibility/PHPCompatibility/issues/373). +- :pushpin: The `NewScalarTypeDeclarations` sniff will now report on new type hints even when the type hint is nullable. [#379](https://github.com/PHPCompatibility/PHPCompatibility/pull/379) +- :twisted_rightwards_arrows: The `NewNowdoc` sniff has been renamed to `NewNowdocQuotedHeredoc` and will now also check for double quoted heredoc identifiers as introduced in PHP 5.3. [#390](https://github.com/PHPCompatibility/PHPCompatibility/pull/390) +- :rewind: The `NewClasses` sniff will now also report anonymous classes which `extend` a new sniff when used in combination with PHPCS 2.4.0-2.8.0. [#432](https://github.com/PHPCompatibility/PHPCompatibility/pull/432). Fixes [#334](https://github.com/PHPCompatibility/PHPCompatibility/issues/334). +- :pencil2: `NewFunctionParameter` sniff: version number precision for two parameters. [#384](https://github.com/PHPCompatibility/PHPCompatibility/pull/384), [#428](https://github.com/PHPCompatibility/PHPCompatibility/pull/428) +- :umbrella: Skipping two unit tests for the `ForbiddenClosureUseVariable` sniff when run on PHPCS 2.5.1 as these cause an infinite loop due to an upstream bug. [#408](https://github.com/PHPCompatibility/PHPCompatibility/pull/408) +- :umbrella: Skipping unit tests involving `trait`s in combination with PHP < 5.4 and PHPCS < 2.4.0 as `trait`s are not recognized in those circumstances. [#431](https://github.com/PHPCompatibility/PHPCompatibility/pull/431) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#385](https://github.com/PHPCompatibility/PHPCompatibility/pull/385), [#387](https://github.com/PHPCompatibility/PHPCompatibility/pull/387), [#415](https://github.com/PHPCompatibility/PHPCompatibility/pull/415), [#423](https://github.com/PHPCompatibility/PHPCompatibility/pull/423), [#424](https://github.com/PHPCompatibility/PHPCompatibility/pull/424) +- :recycle: Minor simplification of the PHPUnit 6 compatibility layer and other test code. [#426](https://github.com/PHPCompatibility/PHPCompatibility/pull/426), [#425](https://github.com/PHPCompatibility/PHPCompatibility/pull/425) +- General housekeeping. [#398](https://github.com/PHPCompatibility/PHPCompatibility/pull/398), [#400](https://github.com/PHPCompatibility/PHPCompatibility/pull/400) +- :wrench: Minor tweaks to the Travis build script. [#409](https://github.com/PHPCompatibility/PHPCompatibility/pull/409) +- :green_heart: The sniffs are now also tested against PHP nightly for consistent results. [#380](https://github.com/PHPCompatibility/PHPCompatibility/pull/380) + +### Fixed +- :fire: Using unbounded ranges in `testVersion` resulted in unreported errors when used with sniffs using the `supportsBelow()` method. This affected the results of approximately half the sniffs. [#430](https://github.com/PHPCompatibility/PHPCompatibility/pull/430) +- :bug: The `ForbiddenNames` sniff would throw false positives for `use` statements with the `final` modifier in traits. [#402](https://github.com/PHPCompatibility/PHPCompatibility/pull/402). +- :bug: The `ForbiddenNames` sniff would fail to report on functions declared to return by reference using a reserved keyword as the function name. [#413](https://github.com/PHPCompatibility/PHPCompatibility/pull/413) +- :bug: The `ForbiddenNames` sniff would only examine the first part of a namespace and not report on reserved keywords used in subsequent parts of a nested namespace. [#419](https://github.com/PHPCompatibility/PHPCompatibility/pull/419) +- :bug: The `ForbiddenNames` sniff would not always correctly report on use statements importing constants or functions using reserved keywords. [#420](https://github.com/PHPCompatibility/PHPCompatibility/pull/420) +- :bug: The `NewKeywords` sniff would sometimes fail to report on the `const` keyword when used in a class, but not for a class constant. [#424](https://github.com/PHPCompatibility/PHPCompatibility/pull/424) +- :green_heart: PHPCS has released version 3.0 and updated the `master` branch to reflect this. This was causing the builds to fail. [#422](https://github.com/PHPCompatibility/PHPCompatibility/pull/422) + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Mark Clements] for their contributions to this version. :clap: + + +## [7.1.3] - 2017-04-02 + +See all related issues and PRs in the [7.1.3 milestone]. + +### Added +- :zap: The `testVersion` config parameter now allows for specifying unbounded ranges. + For example: specifying `-5.6` means: check for compatibility with all PHP versions up to and including PHP 5.6; + Specifying `7.0-` means: check for compatibility with all PHP versions from PHP 7.0 upwards. + For more information about setting the `testVersion`, see [Using the compatibility sniffs](https://github.com/PHPCompatibility/PHPCompatibility#using-the-compatibility-sniffs) in the readme. +- :umbrella: Unit test for multi-line short arrays for the `ShortArray` sniff. [#347](https://github.com/PHPCompatibility/PHPCompatibility/pull/347) +- :umbrella: Various additional unit tests against false positives. [#345](https://github.com/PHPCompatibility/PHPCompatibility/pull/345), [#369](https://github.com/PHPCompatibility/PHPCompatibility/pull/369) +- :umbrella: Unit tests for the `supportsBelow()`, `supportsAbove()` and `getTestVersion()` utility methods. [#363](https://github.com/PHPCompatibility/PHPCompatibility/pull/363) +- :books: Readme: information about installation of the standard using git check-out. [#349](https://github.com/PHPCompatibility/PHPCompatibility/pull/349) +- :books: `Contributing.md` file with information about reporting bugs, requesting features, making pull requests and running the unit tests. [#350](https://github.com/PHPCompatibility/PHPCompatibility/pull/350) + +### Changed +- :pushpin: The `ForbiddenFunctionParametersWithSameName`, `NewScalarTypeDeclarations`, `ParameterShadowSuperGlobals` sniff will now also sniff for and report violations in closures. [#331](https://github.com/PHPCompatibility/PHPCompatibility/pull/331) +- :twisted_rightwards_arrows: :rewind: The check for the PHP 5.3 `nowdoc` structure has been moved from the `NewKeywords` sniff to a new stand-alone `NewNowdoc` sniff which will now also recognize this structure when the sniffs are run on PHP 5.2. [#335](https://github.com/PHPCompatibility/PHPCompatibility/pull/335) +- :rewind: The `ForbiddenNames` sniff will now also correctly recognize reserved keywords used in a declared namespace when run on PHP 5.2. [#362](https://github.com/PHPCompatibility/PHPCompatibility/pull/362) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#360](https://github.com/PHPCompatibility/PHPCompatibility/pull/360) +- :recycle: The unit tests would previously run each test case file against all PHPCompatibility sniffs. Now, they will only be tested against the sniff which the test case file is intended to test. This allows for more test cases to be tested, more precise testing in combination with `testVersion` settings and makes the unit tests run ~6 x faster. + Relevant additional unit tests have been added and others adjusted. [#369](https://github.com/PHPCompatibility/PHPCompatibility/pull/369) +- :recycle: Refactoring/tidying up of some unit test code. [#343](https://github.com/PHPCompatibility/PHPCompatibility/pull/343), [#345](https://github.com/PHPCompatibility/PHPCompatibility/pull/345), [#356](https://github.com/PHPCompatibility/PHPCompatibility/pull/356), [#355](https://github.com/PHPCompatibility/PHPCompatibility/pull/355), [#359](https://github.com/PHPCompatibility/PHPCompatibility/pull/359) +- General housekeeping. [#346](https://github.com/PHPCompatibility/PHPCompatibility/pull/346) +- :books: Readme: Clarify minimum requirements and influence on the results. [#348](https://github.com/PHPCompatibility/PHPCompatibility/pull/348) + +### Removed +- :twisted_rightwards_arrows: Removed the `LongArrays` sniff. The checks it contained have been moved into the `RemovedGlobalVariables` sniff. Both sniffs essentially did the same thing, just for different PHP native superglobals. [#354](https://github.com/PHPCompatibility/PHPCompatibility/pull/354) + +### Fixed +- :bug: The `PregReplaceEModifier` sniff would throw a false positive if a quote character was used as the regex delimiter. [#357](https://github.com/PHPCompatibility/PHPCompatibility/pull/357) +- :bug: `RemovedGlobalVariables` sniff would report false positives for class properties shadowing the removed `$HTTP_RAW_POST_DATA` variables. [#354](https://github.com/PHPCompatibility/PHPCompatibility/pull/354). +- :bug: The `getFQClassNameFromNewToken()` utility function could go into an infinite loop causing PHP to run out of memory when examining unfinished code (examination during live coding). [#338](https://github.com/PHPCompatibility/PHPCompatibility/pull/338), [#342](https://github.com/PHPCompatibility/PHPCompatibility/pull/342) +- :bug: The `determineNamespace()` utility method would in certain cases not break out a loop. [#358](https://github.com/PHPCompatibility/PHPCompatibility/pull/358) +- :wrench: Travis script: Minor tweak for PHP 5.2 compatibility. [#341](https://github.com/PHPCompatibility/PHPCompatibility/pull/341) +- :wrench: The unit test suite is now also compatible with PHPUnit 6. [#365](https://github.com/PHPCompatibility/PHPCompatibility/pull/365) +- :books: Readme: Typo in the composer instructions. [#344](https://github.com/PHPCompatibility/PHPCompatibility/pull/344) + +### Credits +Thanks go out to [Arthur Edamov], [Juliette Reinders Folmer], [Mark Clements] and [Tadas Juozapaitis] for their contributions to this version. :clap: + + +## [7.1.2] - 2017-02-17 + +See all related issues and PRs in the [7.1.2 milestone]. + +### Added +- :star2: New `VariableVariables` sniff to detect variables variables for which the behaviour has changed in PHP 7.0. [#310](https://github.com/PHPCompatibility/PHPCompatibility/pull/310) Fixes [#309](https://github.com/PHPCompatibility/PHPCompatibility/issues/309). +- :star: The `NewReturnTypeDeclarations` sniff will now also sniff for non-scalar return type declarations, i.e. `array`, `callable`, `self` or a class name. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :star: The `NewLanguageConstructs` sniff will now also sniff for the null coalesce equal operator `??=`. This operator is slated to be introduced in PHP 7.2 and PHPCS already accounts for it. [#340](https://github.com/PHPCompatibility/PHPCompatibility/pull/340) +- :star: New `getReturnTypeHintToken()` utility method to the `PHPCompatibility_Sniff` class to retrieve return type hints from function declarations in a cross-PHPCS-version compatible way. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323). +- :star: New `stripVariables()` utility method to the `PHPCompatibility_Sniff` class to strip variables from interpolated text strings. [#341](https://github.com/PHPCompatibility/PHPCompatibility/pull/314). +- :umbrella: Additional unit tests covering previously uncovered code. [#308](https://github.com/PHPCompatibility/PHPCompatibility/pull/308) + +### Changed +- :pushpin: The `MbstringReplaceEModifier`, `PregReplaceEModifier` and `NewExecutionDirectives` sniffs will now also correctly interpret double quoted text strings with interpolated variables. [#341](https://github.com/PHPCompatibility/PHPCompatibility/pull/314), [#324](https://github.com/PHPCompatibility/PHPCompatibility/pull/324). +- :pushpin: The `NewNullableTypes` sniff will now also report on nullable (return) type hints when used with closures. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :pushpin: The `NewReturnTypeDeclarations` sniff will now also report on return type hints when used with closures. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :pushpin: Allow for anonymous classes in the `inClassScope()` utility method. [#315](https://github.com/PHPCompatibility/PHPCompatibility/pull/315) +- :pushpin: The function call parameter related utility functions can now also be used to get the individual items from an array declaration. [#300](https://github.com/PHPCompatibility/PHPCompatibility/pull/300) +- :twisted_rightwards_arrows: The `NewScalarReturnTypeDeclarations` sniff has been renamed to `NewReturnTypeDeclarations`. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :rewind: The `ForbiddenNames` sniff will now also correctly ignore anonymous classes when used in combination with PHPCS < 2.3.4. [#319](https://github.com/PHPCompatibility/PHPCompatibility/pull/319) +- :rewind: The `NewAnonymousClasses` sniff will now correctly recognize and report on anonymous classes when used in combination with PHPCS < 2.5.2. [#325](https://github.com/PHPCompatibility/PHPCompatibility/pull/325) +- :rewind: The `NewGroupUseDeclarations` sniff will now correctly recognize and report on group use statements when used in combination with PHPCS < 2.6.0. [#320](https://github.com/PHPCompatibility/PHPCompatibility/pull/320) +- :rewind: The `NewNullableTypes` sniff will now correctly recognize and report on nullable return types when used in combination with PHPCS < 2.6.0. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :rewind: The `NewReturnTypeDeclarations` sniff will now correctly recognize and report on new return types when used in combination with PHPCS < 2.6.0. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#317](https://github.com/PHPCompatibility/PHPCompatibility/pull/317) +- :recycle: Defer to upstream `hasCondition()` utility method where appropriate. [#315](https://github.com/PHPCompatibility/PHPCompatibility/pull/315) +- :recycle: Minor refactoring of some unit test code. [#304](https://github.com/PHPCompatibility/PHPCompatibility/pull/304), [#303](https://github.com/PHPCompatibility/PHPCompatibility/pull/303), [#318](https://github.com/PHPCompatibility/PHPCompatibility/pull/318) +- :wrench: All unit tests now have appropriate `@group` annotations allowing for quicker/easier testing of a select group of tests/sniffs. [#305](https://github.com/PHPCompatibility/PHPCompatibility/pull/305) +- :wrench: All unit tests now have appropriate `@covers` annotations to improve code coverage reporting and remove bleed through of accidental coverage. [#307](https://github.com/PHPCompatibility/PHPCompatibility/pull/307) +- :wrench: Minor tweaks to the travis script. [#322](https://github.com/PHPCompatibility/PHPCompatibility/pull/322) +- :green_heart: The PHPCompatibility code base itself will now be checked for cross-version compatibility during build testing. [#322](https://github.com/PHPCompatibility/PHPCompatibility/pull/322) + +### Fixed +- :bug: The `ConstantArraysUsingDefine` sniff would throw false positives if the value of the `define()` was retrieved via a function call and an array parameter was passed. [#327](https://github.com/PHPCompatibility/PHPCompatibility/pull/327) +- :bug: The `ForbiddenCallTimePassByReference` sniff would throw false positives on assign by reference within function calls or conditions. [#302](https://github.com/PHPCompatibility/PHPCompatibility/pull/302) Fixes the last two cases reported in [#68](https://github.com/PHPCompatibility/PHPCompatibility/issues/68#issuecomment-231366445) +- :bug: The `ForbiddenGlobalVariableVariableSniff` sniff would only examine the first variable in a `global ...` statement causing unreported issues if subsequent variables were variable variables. [#316](https://github.com/PHPCompatibility/PHPCompatibility/pull/316) +- :bug: The `NewKeywords` sniff would throw a false positive for the `const` keyword when encountered in an interface. [#312](https://github.com/PHPCompatibility/PHPCompatibility/pull/312) +- :bug: The `NewNullableTypes` sniff would not report on nullable return types for namespaced classnames used as a type hint. [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323) +- :bug: The `PregReplaceEModifier` sniff would always consider the first parameter passed as a single regex, while it could also be an array of regexes. This led to false positives and potentially unreported use of the `e` modifier when an array of regexes was passed. [#300](https://github.com/PHPCompatibility/PHPCompatibility/pull/300) +- :bug: The `PregReplaceEModifier` sniff could misidentify the regex delimiter when the regex to be examined was concatenated together from various text strings taken from a compound parameter leading to false positives. [#300](https://github.com/PHPCompatibility/PHPCompatibility/pull/300) +- :white_check_mark: Compatibility with PHPCS 2.7.x. Deal with changed behaviour of the upstream PHP tokenizer and utility function(s). [#313](https://github.com/PHPCompatibility/PHPCompatibility/pull/313), [#323](https://github.com/PHPCompatibility/PHPCompatibility/pull/323), [#326](https://github.com/PHPCompatibility/PHPCompatibility/pull/326), [#340](https://github.com/PHPCompatibility/PHPCompatibility/pull/340) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.1.1] - 2016-12-14 + +See all related issues and PRs in the [7.1.1 milestone]. + +### Added +- :star: `ForbiddenNamesAsDeclared` sniff: detection of the PHP 7.1 `iterable` and `void` reserved keywords when used to name classes, interfaces or traits. [#298](https://github.com/PHPCompatibility/PHPCompatibility/pull/298) + +### Fixed +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would incorrectly throw an error if the `clone` keyword was used with parenthesis. [#299](https://github.com/PHPCompatibility/PHPCompatibility/pull/299). Fixes [#284](https://github.com/PHPCompatibility/PHPCompatibility/issues/284) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.1.0] - 2016-12-14 + +See all related issues and PRs in the [7.1.0 milestone]. + +### Added +- :star: New `stringToErrorCode()`, `arrayKeysToLowercase()` and `addMessage()` utility methods to the `PHPCompatibility_Sniff` class. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291). + +### Changed +- :pushpin: All sniff error messages now have modular error codes allowing for selectively disabling individual checks - and even selectively disabling individual sniff for specific files - without disabling the complete sniff. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :pencil2: Minor changes to some of the error message texts for consistency across sniffs. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :recycle: Refactored the complex version sniffs to reduce code duplication. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :recycle: Miscellaneous other refactoring for improved performance and sniff accuracy. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) +- :umbrella: The unit tests for the `RemovedExtensions` sniff now verify that the correct alternative extension is being suggested. [#291](https://github.com/PHPCompatibility/PHPCompatibility/pull/291) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.8] - 2016-10-31 - :ghost: Spooky! :jack_o_lantern: + +See all related issues and PRs in the [7.0.8 milestone]. + +### Added +- :star2: New `ForbiddenNamesAsDeclared` sniff: detection of the [other reserved keywords](http://php.net/manual/en/reserved.other-reserved-words.php) which are reserved as of PHP 7.0 (or higher). [#287](https://github.com/PHPCompatibility/PHPCompatibility/pull/287). Fixes [#115](https://github.com/PHPCompatibility/PHPCompatibility/issues/115). + These were previously sniffed for by the `ForbiddenNames` and `ForbiddenNamesAsInvokedFunctions` sniffs causing false positives as the rules for their reservation are different from the rules for "normal" [reserved keywords](http://php.net/manual/en/reserved.keywords.php). +- :star: New `inUseScope()` utility method to the `PHPCompatibility_Sniff` class which handles PHPCS cross-version compatibility when determining the scope of a `use` statement. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :umbrella: More unit tests for the `ForbiddenNames` sniff. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). + +### Changed +- :pushpin: _Deprecated_ functionality should throw a `warning`. _Removed_ or otherwise unavailable functionality should throw an `error`. This distinction was previously not consistently applied everywhere. [#286](https://github.com/PHPCompatibility/PHPCompatibility/pull/286) + This change affects the following sniffs: + * `DeprecatedPHP4StyleConstructors` will now throw a `warning` instead of an `error` for deprecated PHP4 style class constructors. + * `ForbiddenCallTimePassByReference` will now throw a `warning` if the `testVersion` is `5.3` and an `error` if the `testVersion` if `5.4` or higher. + * `MbstringReplaceEModifier` will now throw a `warning` instead of an `error` for usage of the deprecated `e` modifier. + * `PregReplaceEModifier` will now throw a `warning` if the `testVersion` is `5.5` or `5.6` and an `error` if the `testVersion` if `7.0` or higher. Fixes [#290](https://github.com/PHPCompatibility/PHPCompatibility/issues/290). + * `TernaryOperators` will now throw an `error` when the `testVersion` < `5.3` and the middle part has been omitted. + * `ValidIntegers` will now throw a `warning` when an invalid binary integer is detected. +- :pencil2: `DeprecatedFunctions` and `DeprecatedIniDirectives` sniffs: minor change in the sniff error message text. Use _"removed"_ rather than the ominous _"forbidden"_. [#285](https://github.com/PHPCompatibility/PHPCompatibility/pull/285) + Also updated relevant internal variable names and documentation to match. + +### Fixed +- :bug: `ForbiddenNames` sniff would throw false positives for `use` statements which changed the visibility of methods in traits. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :bug: `ForbiddenNames` sniff would not report reserved keywords when used in combination with `use function` or `use const`. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :bug: `ForbiddenNames` sniff would potentially - unintentionally - skip over tokens, thereby - potentially - not reporting all errors. [#271](https://github.com/PHPCompatibility/PHPCompatibility/pull/271). +- :wrench: Composer config: `prefer-stable` should be a root element of the json file. Fixes [#277](https://github.com/PHPCompatibility/PHPCompatibility/issues/277). + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.7] - 2016-10-20 + +See all related issues and PRs in the [7.0.7 milestone]. + +### Added +- :star2: New `ForbiddenBreakContinueOutsideLoop` sniff: verify that `break`/`continue` is not used outside of a loop structure. This will cause fatal errors since PHP 7.0. [#278](https://github.com/PHPCompatibility/PHPCompatibility/pull/278). Fixes [#275](https://github.com/PHPCompatibility/PHPCompatibility/issues/275) +- :star2: New `NewConstVisibility` sniff: detect visibility indicators for `class` and `interface` constants as introduced in PHP 7.1. [#280](https://github.com/PHPCompatibility/PHPCompatibility/pull/280). Fixes [#249](https://github.com/PHPCompatibility/PHPCompatibility/issues/249) +- :star2: New `NewHashAlgorithms` sniff to check used hash algorithms against the PHP version in which they were introduced. [#242](https://github.com/PHPCompatibility/PHPCompatibility/pull/242) +- :star2: New `NewMultiCatch` sniff: detect catch statements catching multiple Exceptions as introduced in PHP 7.1. [#281](https://github.com/PHPCompatibility/PHPCompatibility/pull/281). Fixes [#251](https://github.com/PHPCompatibility/PHPCompatibility/issues/251) +- :star2: New `NewNullableTypes` sniff: detect nullable parameter and return type hints (only supported in PHPCS >= 2.3.4) as introduced in PHP 7.1. [#282](https://github.com/PHPCompatibility/PHPCompatibility/pull/282). Fixes [#247](https://github.com/PHPCompatibility/PHPCompatibility/issues/247) +- :star: `DeprecatedIniDirectives` sniff: recognize PHP 7.1 removed `session` ini directives. [#256](https://github.com/PHPCompatibility/PHPCompatibility/pull/256) +- :star: `NewFunctions` sniff: recognize new `socket_export_stream()` function as introduced in PHP 7.0.7. [#264](https://github.com/PHPCompatibility/PHPCompatibility/pull/264) +- :star: `NewFunctions` sniff: recognize new `curl_...()`, `is_iterable()`, `pcntl_async_signals()`, `session_create_id()`, `session_gc()` functions as introduced in PHP 7.1. [#273](https://github.com/PHPCompatibility/PHPCompatibility/pull/273) +- :star: `NewFunctionParameters` sniff: recognize new OpenSSL function parameters as introduced in PHP 7.1. [#258](https://github.com/PHPCompatibility/PHPCompatibility/pull/258) +- :star: `NewIniDirectives` sniff: recognize new `session` ini directives as introduced in PHP 7.1. [#259](https://github.com/PHPCompatibility/PHPCompatibility/pull/259) +- :star: `NewScalarReturnTypeDeclarations` sniff: recognize PHP 7.1 `void` return type hint. [#250](https://github.com/PHPCompatibility/PHPCompatibility/pull/250) +- :star: `NewScalarTypeDeclarations` sniff: recognize PHP 7.1 `iterable` type hint. [#255](https://github.com/PHPCompatibility/PHPCompatibility/pull/255) +- :star: Recognize the PHP 7.1 deprecated `mcrypt` functionality in the `RemovedExtensions`, `DeprecatedFunctions` and `DeprecatedIniDirectives` sniffs. [#257](https://github.com/PHPCompatibility/PHPCompatibility/pull/257) + +### Changed +- :pushpin: `LongArrays` sniff used to only throw `warning`s. It will now throw `error`s for PHP versions in which the long superglobals have been removed. [#270](https://github.com/PHPCompatibility/PHPCompatibility/pull/270) +- :pushpin: The `NewIniDirectives` sniff used to always throw an `warning`. Now it will throw an `error` when a new ini directive is used in combination with `ini_set()`. [#246](https://github.com/PHPCompatibility/PHPCompatibility/pull/246). +- :pushpin: `RemovedHashAlgorithms` sniff: also recognize removed algorithms when used with the PHP 5.5+ `hash_pbkdf2()` function. [#240](https://github.com/PHPCompatibility/PHPCompatibility/pull/240) +- :pushpin: Properly recognize nullable type hints in the `getMethodParameters()` utility method. [#282](https://github.com/PHPCompatibility/PHPCompatibility/pull/282) +- :pencil2: `DeprecatedPHP4StyleConstructors` sniff: minor error message text fix. [#236](https://github.com/PHPCompatibility/PHPCompatibility/pull/236) +- :pencil2: `NewIniDirectives` sniff: improved precision for the introduction version numbers being reported. [#246](https://github.com/PHPCompatibility/PHPCompatibility/pull/246) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#238](https://github.com/PHPCompatibility/PHPCompatibility/pull/238), [#244](https://github.com/PHPCompatibility/PHPCompatibility/pull/244), [#240](https://github.com/PHPCompatibility/PHPCompatibility/pull/240), [#276](https://github.com/PHPCompatibility/PHPCompatibility/pull/276) +- :umbrella: Re-activate the unit tests for the `NewScalarReturnTypeDeclarations` sniff. [#250](https://github.com/PHPCompatibility/PHPCompatibility/pull/250) + +### Fixed +- :bug: The `DeprecatedPHP4StyleConstructors` sniff would not report errors when the case of the class name and the PHP4 constructor function name did not match. [#236](https://github.com/PHPCompatibility/PHPCompatibility/pull/236) +- :bug: `LongArrays` sniff would report false positives for class properties shadowing removed PHP superglobals. [#270](https://github.com/PHPCompatibility/PHPCompatibility/pull/270). Fixes [#268](https://github.com/PHPCompatibility/PHPCompatibility/issues/268). +- :bug: The `NewClasses` sniff would not report errors when the case of the class name used and "official" class name did not match. [#237](https://github.com/PHPCompatibility/PHPCompatibility/pull/237) +- :bug: The `NewIniDirectives` sniff would report violations against the PHP version in which the ini directive was introduced. This should be the version below it. [#246](https://github.com/PHPCompatibility/PHPCompatibility/pull/246) +- :bug: `PregReplaceEModifier` sniff would report false positives for compound regex parameters with different quote types. [#266](https://github.com/PHPCompatibility/PHPCompatibility/pull/266). Fixes [#265](https://github.com/PHPCompatibility/PHPCompatibility/issues/265). +- :bug: `RemovedGlobalVariables` sniff would report false positives for lowercase/mixed cased variables shadowing superglobals. [#245](https://github.com/PHPCompatibility/PHPCompatibility/pull/245). +- :bug: The `RemovedHashAlgorithms` sniff would not report errors when the case of the hash function name used and "official" class name did not match. [#240](https://github.com/PHPCompatibility/PHPCompatibility/pull/240) +- :bug: The `ShortArray` sniff would report all violations on the line of the PHP open tag, not on the lines of the short array open/close tags. [#238](https://github.com/PHPCompatibility/PHPCompatibility/pull/238) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.6] - 2016-09-23 + +See all related issues and PRs in the [7.0.6 milestone]. + +### Added +- :star: New `stripQuotes()` utility method in the `PHPCompatibility_Sniff` base class to strip quotes which surround text strings in a consistent manner. [#224](https://github.com/PHPCompatibility/PHPCompatibility/pull/224) +- :books: Readme: Add _PHP Version Support_ section. [#225](https://github.com/PHPCompatibility/PHPCompatibility/pull/225) + +### Changed +- :pushpin: The `ForbiddenCallTimePassByReference` sniff will now also report the deprecation as of PHP 5.3, not just its removal as of PHP 5.4. [#203](https://github.com/PHPCompatibility/PHPCompatibility/pull/203) +- :pushpin: The `NewFunctionArrayDereferencing` sniff will now also check _method_ calls for array dereferencing, not just function calls. [#229](https://github.com/PHPCompatibility/PHPCompatibility/pull/229). Fixes [#227](https://github.com/PHPCompatibility/PHPCompatibility/issues/227). +- :pencil2: The `NewExecutionDirectives` sniff will now throw `warning`s instead of `error`s for invalid values encountered in execution directives. [#223](https://github.com/PHPCompatibility/PHPCompatibility/pull/223) +- :pencil2: Minor miscellaneous fixes. [#231](https://github.com/PHPCompatibility/PHPCompatibility/pull/231) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#219](https://github.com/PHPCompatibility/PHPCompatibility/pull/219), [#203](https://github.com/PHPCompatibility/PHPCompatibility/pull/203) +- :recycle: Defer to upstream `findImplementedInterfaceNames()` utility method when it exists. [#222](https://github.com/PHPCompatibility/PHPCompatibility/pull/222) +- :wrench: Exclude the test files from analysis by Scrutinizer CI. [#230](https://github.com/PHPCompatibility/PHPCompatibility/pull/230) + +### Removed +- :no_entry_sign: Some redundant code. [#232](https://github.com/PHPCompatibility/PHPCompatibility/pull/232) + +### Fixed +- :bug: The `EmptyNonVariable` sniff would throw false positives for variable variables and for array access with a (partially) variable array index. [#212](https://github.com/PHPCompatibility/PHPCompatibility/pull/212). Fixes [#210](https://github.com/PHPCompatibility/PHPCompatibility/issues/210). +- :bug: The `NewFunctionArrayDereferencing` sniff would throw false positives for lines of code containing both a function call as well as square brackets, even when they were unrelated. [#228](https://github.com/PHPCompatibility/PHPCompatibility/pull/228). Fixes [#226](https://github.com/PHPCompatibility/PHPCompatibility/issues/226). +- :bug: `ParameterShadowSuperGlobals` sniff would report false positives for lowercase/mixed cased variables shadowing superglobals. [#218](https://github.com/PHPCompatibility/PHPCompatibility/pull/218). Fixes [#214](https://github.com/PHPCompatibility/PHPCompatibility/issues/214). +- :bug: The `determineNamespace()` utility method now accounts properly for namespaces within scoped `declare()` statements. [#221](https://github.com/PHPCompatibility/PHPCompatibility/pull/221) +- :books: Readme: Logo alignment in the Credits section. [#233](https://github.com/PHPCompatibility/PHPCompatibility/pull/233) + +### Credits +Thanks go out to [Jason Stallings], [Juliette Reinders Folmer] and [Mark Clements] for their contributions to this version. :clap: + + +## [7.0.5] - 2016-09-08 + +See all related issues and PRs in the [7.0.5 milestone]. + +### Added +- :star2: New `MbstringReplaceEModifier` sniff to detect the use of the PHP 7.1 deprecated `e` modifier in Mbstring regex functions. [#202](https://github.com/PHPCompatibility/PHPCompatibility/pull/202) +- :star: The `ForbiddenBreakContinueVariableArguments` sniff will now also report on `break 0`/`continue 0` which is not allowed since PHP 5.4. [#209](https://github.com/PHPCompatibility/PHPCompatibility/pull/209) +- :star: New `getFunctionCallParameters()`, `getFunctionCallParameter()` utility methods in the `PHPCompatibility_Sniff` base class. [#170](https://github.com/PHPCompatibility/PHPCompatibility/pull/170) +- :star: New `tokenHasScope()` utility method in the `PHPCompatibility_Sniff` base class. [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189) +- :umbrella: Unit test for `goto` and `callable` detection and some other miscellanous extra unit tests for the `NewKeywords` sniff. [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189) +- :books: Readme: Information for sniff developers about running unit tests for _other_ sniff libraries using the PHPCS native test framework without running into conflicts with the PHPCompatibility specific unit test framework. [#217](https://github.com/PHPCompatibility/PHPCompatibility/pull/217) + +### Changed +- :pushpin: The `ForbiddenNames` sniff will now also check interface declarations for usage of reserved keywords. [#200](https://github.com/PHPCompatibility/PHPCompatibility/pull/200) +- :pushpin: `PregReplaceEModifier` sniff: improved handling of regexes build up of a combination of variables, function calls and/or text strings. [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201) +- :rewind: The `NewKeywords` sniff will now also correctly recognize new keywords when used in combination with older PHPCS versions and/or run on older PHP versions. [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189) +- :pencil2: `PregReplaceEModifier` sniff: minor improvement to the error message text. [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#170](https://github.com/PHPCompatibility/PHPCompatibility/pull/170), [#188](https://github.com/PHPCompatibility/PHPCompatibility/pull/188), [#189](https://github.com/PHPCompatibility/PHPCompatibility/pull/189), [#199](https://github.com/PHPCompatibility/PHPCompatibility/pull/199), [#200](https://github.com/PHPCompatibility/PHPCompatibility/pull/200), [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201), [#208](https://github.com/PHPCompatibility/PHPCompatibility/pull/208) +- :wrench: The unit tests for the utility methods have been moved to their own subdirectory within `Tests`. [#215](https://github.com/PHPCompatibility/PHPCompatibility/pull/215) +- :green_heart: The sniffs are now also tested against PHP 7.1 for consistent results. [#216](https://github.com/PHPCompatibility/PHPCompatibility/pull/216) + +### Removed +- :no_entry_sign: Some redundant code. [26d0b6](https://github.com/PHPCompatibility/PHPCompatibility/commit/26d0b6cf0921f75d93a4faaf09c390f386dde9ff) and [841616](https://github.com/PHPCompatibility/PHPCompatibility/commit/8416162ea81f4067226324f5948f4a50f7958a9b) + +### Fixed +- :bug: `ConstantArraysUsingDefine` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#199](https://github.com/PHPCompatibility/PHPCompatibility/pull/199) +- :bug: The `DeprecatedIniDirectives` and `NewIniDirectives` sniffs could potentially trigger on the ini value instead of the ini directive name. [#170](https://github.com/PHPCompatibility/PHPCompatibility/pull/170) +- :bug: `ForbiddenNames` sniff: Reserved keywords when used as the name of a constant declared using `define()` would always be reported independently of the `testVersion` set. [#200](https://github.com/PHPCompatibility/PHPCompatibility/pull/200) +- :bug: `PregReplaceEModifier` sniff would not report errors when the function name used was not in lowercase. [#201](https://github.com/PHPCompatibility/PHPCompatibility/pull/201) +- :bug: `TernaryOperators` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#188](https://github.com/PHPCompatibility/PHPCompatibility/pull/188) +- :bug: The `getFQClassNameFromNewToken()` and `getFQClassNameFromDoubleColonToken()` utility methods would get confused when the class name was a variable instead of being hard-coded, resulting in a PHP warning being thown. [#206](https://github.com/PHPCompatibility/PHPCompatibility/pull/206). Fixes [#205](https://github.com/PHPCompatibility/PHPCompatibility/issues/205). +- :bug: The `getFunctionCallParameters()` utility method would incorrectly identify an extra parameter if the last parameter passed to a function would have an - unnecessary - comma after it. The `getFunctionCallParameters()` utility method also did not handle parameters passed as short arrays correctly. [#213](https://github.com/PHPCompatibility/PHPCompatibility/pull/213). Fixes [#211](https://github.com/PHPCompatibility/PHPCompatibility/issues/211). +- :umbrella: Unit tests for the `NewFunctionArrayDereferencing` sniff were not being run due to a naming error. [#208](https://github.com/PHPCompatibility/PHPCompatibility/pull/208) +- :books: Readme: Information about setting the `testVersion` from a custom ruleset was incorrect. [#204](https://github.com/PHPCompatibility/PHPCompatibility/pull/204) +- :wrench: Path to PHPCS in the unit tests breaking for non-Composer installs. [#198](https://github.com/PHPCompatibility/PHPCompatibility/pull/198) + +### Credits +Thanks go out to [Juliette Reinders Folmer] and [Yoshiaki Yoshida] for their contributions to this version. :clap: + + +## [7.0.4] - 2016-08-20 + +See all related issues and PRs in the [7.0.4 milestone]. + +### Added +- :star2: New `EmptyNonVariable` sniff: detection of empty being used on non-variables for PHP < 5.5. [#187](https://github.com/PHPCompatibility/PHPCompatibility/pull/187) +- :star2: New `NewMagicMethods` sniff: detection of declaration of magic methods before the method became "magic". Includes a check for the changed behaviour for the `__toString()` magic method in PHP 5.2. [#176](https://github.com/PHPCompatibility/PHPCompatibility/pull/176). Fixes [#64](https://github.com/PHPCompatibility/PHPCompatibility/issues/64). +- :star2: New `RemovedAlternativePHPTags` sniff: detection of ASP and script open tags for which support was removed in PHP 7.0. [#184](https://github.com/PHPCompatibility/PHPCompatibility/pull/184), [#193](https://github.com/PHPCompatibility/PHPCompatibility/pull/193). Fixes [#127](https://github.com/PHPCompatibility/PHPCompatibility/issues/127). +- :star: `NonStaticMagicMethods` sniff: detection of the `__callStatic()`, `__sleep()`, `__toString()` and `__set_state()` magic methods. +- :green_heart: Lint all non-test case files for syntax errors during the build testing by Travis. [#192](https://github.com/PHPCompatibility/PHPCompatibility/pull/192) + +### Changed +- :pushpin: `NonStaticMagicMethods` sniff: will now also sniff `trait`s for magic methods. [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174) +- :pushpin: `NonStaticMagicMethods` sniff: will now also check for magic methods which should be declared as `static`. [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#178](https://github.com/PHPCompatibility/PHPCompatibility/pull/178), [#179](https://github.com/PHPCompatibility/PHPCompatibility/pull/179), [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174), [#171](https://github.com/PHPCompatibility/PHPCompatibility/pull/171) +- :recycle: The unit test suite now internally caches PHPCS run results in combination with a set `testVersion` to speed up the running of the unit tests. These are now ~3 x faster. [#148](https://github.com/PHPCompatibility/PHPCompatibility/pull/148) +- :books: Readme: Minor clarification of the minimum requirements. +- :books: Readme: Advise to use the latest stable version of this repository. +- :wrench: The unit tests can now be run with PHPCS installed in an arbitrary location by passing the location through an environment option. [#191](https://github.com/PHPCompatibility/PHPCompatibility/pull/191). +- :wrench: Improved coveralls configuration and compatibility. [#194](https://github.com/PHPCompatibility/PHPCompatibility/pull/194) +- :green_heart: The sniffs are now also tested against PHP 5.2 for consistent results. Except for namespace, trait and group use related errors, most sniffs work as intended on PHP 5.2. [#196](https://github.com/PHPCompatibility/PHPCompatibility/pull/196) + +### Fixed +- :bug: The `ForbiddenBreakContinueVariableArguments` sniff would not report on `break`/`continue` with a closure as an argument. [#171](https://github.com/PHPCompatibility/PHPCompatibility/pull/171) +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would not report on reserved keywords which were not lowercase. [#186](https://github.com/PHPCompatibility/PHPCompatibility/pull/186) +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would not report on the `goto` and `namespace` keywords when run on PHP 5.2. [#193](https://github.com/PHPCompatibility/PHPCompatibility/pull/193) +- :bug: `NewAnonymousClasses` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#195](https://github.com/PHPCompatibility/PHPCompatibility/pull/195). +- :bug: `NewGroupUseDeclarations` sniff: the version check logic was reversed causing the error not to be reported in certain circumstances. [#190](https://github.com/PHPCompatibility/PHPCompatibility/pull/190). +- :bug: The `NonStaticMagicMethods` sniff would not report on magic methods when the function name as declared was not in the same case as used in the PHP manual. [#174](https://github.com/PHPCompatibility/PHPCompatibility/pull/174) +- :wrench: The unit tests would exit with `0` if PHPCS could not be found. [#191](https://github.com/PHPCompatibility/PHPCompatibility/pull/191) +- :green_heart: The PHPCompatibility library itself was not fully compatible with PHP 5.2. [#193](https://github.com/PHPCompatibility/PHPCompatibility/pull/193) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.3] - 2016-08-18 + +See all related issues and PRs in the [7.0.3 milestone]. + +### Added +- :star2: New `InternalInterfaces` sniff: detection of internal PHP interfaces being which should not be implemented by user land classes. [#144](https://github.com/PHPCompatibility/PHPCompatibility/pull/144) +- :star2: New `LateStaticBinding` sniff: detection of PHP 5.3 late static binding. [#177](https://github.com/PHPCompatibility/PHPCompatibility/pull/177) +- :star2: New `NewExecutionDirectives` sniff: verify execution directives set with `declare()`. [#169](https://github.com/PHPCompatibility/PHPCompatibility/pull/169) +- :star2: New `NewInterfaces` sniff: detection of the use of newly introduced PHP native interfaces. This sniff will also detect unsupported methods when a class implements the `Serializable` interface. [#144](https://github.com/PHPCompatibility/PHPCompatibility/pull/144) +- :star2: New `RequiredOptionalFunctionParameters` sniff: detection of missing function parameters which were required in earlier PHP versions only to become optional in later versions. [#165](https://github.com/PHPCompatibility/PHPCompatibility/pull/165) +- :star2: New `ValidIntegers` sniff: detection of binary integers for PHP < 5.4, detection of hexademical numeric strings for which recognition as hex integers was removed in PHP 7.0, detection of invalid binary and octal integers. [#160](https://github.com/PHPCompatibility/PHPCompatibility/pull/160). Fixes [#55](https://github.com/PHPCompatibility/PHPCompatibility/issues/55). +- :star: `DeprecatedExtensions` sniff: detect removal of the `ereg` extension in PHP 7. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :star: `DeprecatedFunctions` sniff: detection of the PHP 5.0.5 deprecated `php_check_syntax()` and PHP 5.4 deprecated `mysqli_get_cache_stats()` functions. [#155](https://github.com/PHPCompatibility/PHPCompatibility/pull/155). +- :star: `DeprecatedFunctions` sniff: detect deprecation of a number of the `mysqli` functions in PHP 5.3. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :star: `DeprecatedFunctions` sniff: detect removal of the `call_user_method()`, `ldap_sort()`, `ereg_*()` and `mysql_*()` functions in PHP 7.0. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :star: `DeprecatedIniDirectives` sniff: detection of a _lot_ more deprecated/removed ini directives. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :star: `NewFunctionParameters` sniff: detection of a _lot_ more new function parameters. [#164](https://github.com/PHPCompatibility/PHPCompatibility/pull/164) +- :star: `NewFunctions` sniff: detection of numerous extra new functions. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :star: `NewIniDirectives` sniff: detection of a _lot_ more new ini directives. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :star: `NewLanguageConstructs` sniff: detection of the PHP 5.6 ellipsis `...` construct. [#175](https://github.com/PHPCompatibility/PHPCompatibility/pull/175) +- :star: `NewScalarTypeDeclarations` sniff: detection of PHP 5.1 `array` and PHP 5.4 `callable` type hints. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :star: `RemovedFunctionParameters` sniff: detection of a few extra removed function parameters. [#163](https://github.com/PHPCompatibility/PHPCompatibility/pull/163) +- :star: Detection of functions and methods with a double underscore prefix as these are reserved by PHP for future use. The existing upstream `Generic.NamingConventions.CamelCapsFunctionName` sniff is re-used for this with some customization. [#173](https://github.com/PHPCompatibility/PHPCompatibility/pull/173) +- :star: New `getFQClassNameFromNewToken()`, `getFQExtendedClassName()`, `getFQClassNameFromDoubleColonToken()`, `getFQName()`, `isNamespaced()`, `determineNamespace()` and `getDeclaredNamespaceName()` utility methods in the `PHPCompatibility_Sniff` base class for namespace determination. [#162](https://github.com/PHPCompatibility/PHPCompatibility/pull/162) +- :recycle: New `inClassScope()` utility method in the `PHPCompatibility_Sniff` base class. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :recycle: New `doesFunctionCallHaveParameters()` and `getFunctionCallParameterCount()` utility methods in the `PHPCompatibility_Sniff` base class. [#153](https://github.com/PHPCompatibility/PHPCompatibility/pull/153) +- :umbrella: Unit test for `__halt_compiler()` detection by the `NewKeywords` sniff. +- :umbrella: Unit tests for the `NewFunctions` sniff. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :umbrella: Unit tests for the `ParameterShadowSuperGlobals` sniff. [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180) +- :wrench: Minimal config for Scrutinizer CI. [#145](https://github.com/PHPCompatibility/PHPCompatibility/pull/145). + +### Changed +- :pushpin: The `DeprecatedIniDirectives` and the `NewIniDirectives` sniffs will now indicate an alternative ini directive in case the directive has been renamed. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :pushpin: The `NewClasses` sniff will now also report on new classes being extended by child classes. [#140](https://github.com/PHPCompatibility/PHPCompatibility/pull/140). +- :pushpin: The `NewClasses` sniff will now also report on static use of new classes. [#162](https://github.com/PHPCompatibility/PHPCompatibility/pull/162). +- :pushpin: The `NewScalarTypeDeclarations` sniff will now throw an error on use of type hints pre-PHP 5.0. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :pushpin: The `NewScalarTypeDeclarations` sniff will now verify type hints used against typical mistakes. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :pushpin: The `ParameterShadowSuperGlobals` sniff will now do a case-insensitive variable name compare. [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180) +- :pushpin: The `RemovedFunctionParameters` sniff will now also report `warning`s on deprecation of function parameters. [#163](https://github.com/PHPCompatibility/PHPCompatibility/pull/163) +- :twisted_rightwards_arrows: The check for `JsonSerializable` has been moved from the `NewClasses` sniff to the `NewInterfaces` sniff. [#162](https://github.com/PHPCompatibility/PHPCompatibility/pull/162) +- :rewind: The `NewLanguageConstructs` sniff will now also recognize new language constructs when used in combination with PHPCS 1.5.x. [#175](https://github.com/PHPCompatibility/PHPCompatibility/pull/175) +- :pencil2: `NewFunctionParameters` sniff: use correct name for the new parameter for the `dirname()` function. [#164](https://github.com/PHPCompatibility/PHPCompatibility/pull/164) +- :pencil2: `NewScalarTypeDeclarations` sniff: minor change in the sniff error message text. [#168](https://github.com/PHPCompatibility/PHPCompatibility/pull/168) +- :pencil2: `RemovedFunctionParameters` sniff: minor change in the sniff error message text. [#163](https://github.com/PHPCompatibility/PHPCompatibility/pull/163) +- :pencil2: The `ParameterShadowSuperGlobals` sniff now extends the `PHPCompatibility_Sniff` class. [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180) +- :recycle: Various (minor) refactoring for improved performance and sniff accuracy. [#181](https://github.com/PHPCompatibility/PHPCompatibility/pull/181), [#182](https://github.com/PHPCompatibility/PHPCompatibility/pull/182), [#166](https://github.com/PHPCompatibility/PHPCompatibility/pull/166), [#167](https://github.com/PHPCompatibility/PHPCompatibility/pull/167), [#172](https://github.com/PHPCompatibility/PHPCompatibility/pull/172), [#180](https://github.com/PHPCompatibility/PHPCompatibility/pull/180), [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146), [#138](https://github.com/PHPCompatibility/PHPCompatibility/pull/138) +- :recycle: Various refactoring to remove code duplication in the unit tests and add proper test skip notifications where relevant. [#139](https://github.com/PHPCompatibility/PHPCompatibility/pull/139), [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) + +### Fixed +- :bug: The `DeprecatedFunctions` sniff was reporting an incorrect deprecation/removal version number for a few functions. [#149](https://github.com/PHPCompatibility/PHPCompatibility/pull/149) +- :bug: The `DeprecatedIniDirectives` sniff was in select cases reporting deprecation of an ini directive prior to removal, while the ini directive was never deprecated prior to its removal. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :bug: The `DeprecatedPHP4StyleConstructors` sniff would cause false positives for methods with the same name as the class in namespaced classes. [#167](https://github.com/PHPCompatibility/PHPCompatibility/pull/167) +- :bug: The `ForbiddenEmptyListAssignment` sniff did not report errors when there were only comments or parentheses between the list parentheses. [#166](https://github.com/PHPCompatibility/PHPCompatibility/pull/166) +- :bug: The `ForbiddenEmptyListAssignment` sniff will no longer cause false positives during live coding. [#166](https://github.com/PHPCompatibility/PHPCompatibility/pull/166) +- :bug: The `NewClasses` sniff would potentially misidentify namespaced classes as PHP native classes. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/162) +- :bug: The `NewFunctions` sniff would fail to identify called functions when the function call was not lowercase. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :bug: The `NewFunctions` sniff would potentially misidentify namespaced userland functions as new functions. [#161](https://github.com/PHPCompatibility/PHPCompatibility/pull/161) +- :bug: The `NewIniDirectives` sniff was reporting an incorrect introduction version number for a few ini directives. [#146](https://github.com/PHPCompatibility/PHPCompatibility/pull/146) +- :bug: `NewKeywords` sniff: the use of the `const` keyword should only be reported when used outside of a class for PHP < 5.3. [#147](https://github.com/PHPCompatibility/PHPCompatibility/pull/147). Fixes [#129](https://github.com/PHPCompatibility/PHPCompatibility/issues/129). +- :bug: The `RemovedExtensions` sniff was incorrectly reporting a number of extensions as being removed in PHP 5.3 while they were actually removed in PHP 5.1. [#156](https://github.com/PHPCompatibility/PHPCompatibility/pull/156) +- :bug: :recycle: The `NewFunctionParameters` and `RemovedFunctionParameters` now use the new `doesFunctionCallHaveParameters()` and `getFunctionCallParameterCount()` utility methods for improved accuracy in identifying function parameters. This fixes several false positives. [#153](https://github.com/PHPCompatibility/PHPCompatibility/pull/153) Fixes [#120](https://github.com/PHPCompatibility/PHPCompatibility/issues/120), [#151](https://github.com/PHPCompatibility/PHPCompatibility/issues/151), [#152](https://github.com/PHPCompatibility/PHPCompatibility/issues/152). +- :bug: A number of sniffs would return `false` if the examined construct was not found. This could potentially cause race conditions/infinite sniff loops. [#138](https://github.com/PHPCompatibility/PHPCompatibility/pull/138) +- :wrench: The unit tests would fail to run when used in combination with a PEAR install of PHPCS. [#157](https://github.com/PHPCompatibility/PHPCompatibility/pull/157). +- :green_heart: Unit tests failing against PHPCS 2.6.1. [#158](https://github.com/PHPCompatibility/PHPCompatibility/pull/158) + The unit tests *will* still fail against PHPCS 2.6.2 due to a bug in PHPCS itself. This bug does not affect the running of the sniffs outside of a unit test context. + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.2] - 2016-08-03 + +See all related issues and PRs in the [7.0.2 milestone]. + +### Added +- :star: `RemovedExtensions` sniff: ability to whitelist userland functions for which the function prefix overlaps with a prefix of a deprecated/removed extension. [#130](https://github.com/PHPCompatibility/PHPCompatibility/pull/130). Fixes [#123](https://github.com/PHPCompatibility/PHPCompatibility/issues/123). + To use this feature, add the `functionWhitelist` property in your custom ruleset. For more information, see the [README](https://github.com/PHPCompatibility/PHPCompatibility#phpcompatibility-specific-options). + +### Changed +- :pencil2: A number of sniffs contained `public` class properties. Within PHPCS, `public` properties can be overruled via a custom ruleset. This was not the intention, so the visibility of these properties has been changed to `protected`. [#135](https://github.com/PHPCompatibility/PHPCompatibility/pull/135) +- :wrench: Composer config: Stable packages are preferred over unstable/dev. +- :pencil2: Ruleset name. [#134](https://github.com/PHPCompatibility/PHPCompatibility/pull/134) + +### Credits +Thanks go out to [Juliette Reinders Folmer] for her contributions to this version. :clap: + + +## [7.0.1] - 2016-08-02 + +See all related issues and PRs in the [7.0.1 milestone]. + +### Changed +- :pushpin: The `DeprecatedIniDirectives` sniff used to throw an `error` when a deprecated ini directive was used in combination with `ini_get()`. It will now throw a `warning` instead. [#122](https://github.com/PHPCompatibility/PHPCompatibility/pull/122) Fixes [#119](https://github.com/PHPCompatibility/PHPCompatibility/issues/119). + Usage of deprecated ini directives in combination with `ini_set()` will still throw an `error`. +- :pushpin: The `PregReplaceEModifier` sniff now also detects the `e` modifier when used with the `preg_filter()` function. While this is undocumented, the `e` modifier was supported by the `preg_filter()` function as well. [#128](https://github.com/PHPCompatibility/PHPCompatibility/pull/128) +- :pencil2: The `RemovedExtensions` sniff contained superfluous deprecation information in the error message. [#131](https://github.com/PHPCompatibility/PHPCompatibility/pull/131) + +### Removed +- :wrench: Duplicate builds from the Travis CI build matrix. [#132](https://github.com/PHPCompatibility/PHPCompatibility/pull/132) + +### Fixed +- :bug: The `ForbiddenNames` sniff did not allow for the PHP 5.6 `use function ...` and `use const ...` syntax. [#126](https://github.com/PHPCompatibility/PHPCompatibility/pull/126) Fixes [#124](https://github.com/PHPCompatibility/PHPCompatibility/issues/124). +- :bug: The `NewClasses` sniff failed to detect new classes when the class was instantiated without parenthesis, i.e. `new NewClass;`. [#121](https://github.com/PHPCompatibility/PHPCompatibility/pull/121) +- :bug: The `PregReplaceEModifier` sniff failed to detect the `e` modifier when using bracket delimiters for the regex other than the `{}` brackets. [#128](https://github.com/PHPCompatibility/PHPCompatibility/pull/128) +- :green_heart: Unit tests failing against PHPCS 2.6.1. + +### Credits +Thanks go out to [Jason Stallings], [Juliette Reinders Folmer] and [Ryan Neufeld] for their contributions to this version. :clap: + + +## [7.0] - 2016-07-02 + +See all related issues and PRs in the [7.0 milestone]. + +### Added +- :zap: Ability to specify a range of PHP versions against which to test your code base for compatibility, i.e. `--runtime-set testVersion 5.0-5.4` will now test your code for compatibility with PHP 5.0 up to PHP 5.4. [#99](https://github.com/PHPCompatibility/PHPCompatibility/pull/99) +- :star2: New `NewFunctionArrayDereferencing` sniff to detect function array dereferencing as introduced in PHP 5.4. Fixes [#52](https://github.com/PHPCompatibility/PHPCompatibility/issues/52). +- :star2: New `ShortArray` sniff to detect short array syntax as introduced in PHP 5.4. [#97](https://github.com/PHPCompatibility/PHPCompatibility/pull/97). Fixes [#47](https://github.com/PHPCompatibility/PHPCompatibility/issues/47). +- :star2: New `TernaryOperators` sniff to detect ternaries without the middle part (`elvis` operator) as introduced in PHP 5.3. [#101](https://github.com/PHPCompatibility/PHPCompatibility/pull/101), [#103](https://github.com/PHPCompatibility/PHPCompatibility/pull/103). Fixes [#49](https://github.com/PHPCompatibility/PHPCompatibility/issues/49). +- :star2: New `ConstantArraysUsingDefine` sniff to detect constants declared using `define()` being assigned an `array` value which was not allowed prior to PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `DeprecatedPHP4StyleConstructors` sniff to detect PHP 4 style class constructor methods which are deprecated as of PHP 7. [#109](https://github.com/PHPCompatibility/PHPCompatibility/pull/109). +- :star2: New `ForbiddenEmptyListAssignment` sniff to detect empty list() assignments which have been removed in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenFunctionParametersWithSameName` sniff to detect functions declared with multiple same-named parameters which is no longer accepted since PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenGlobalVariableVariable` sniff to detect variable variables being made `global` which is not allowed since PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenNegativeBitshift` sniff to detect bitwise shifts by negative number which will throw an ArithmeticError in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `ForbiddenSwitchWithMultipleDefaultBlocks` sniff to detect switch statements with multiple default blocks which is not allowed since PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewAnonymousClasses` sniff to detect anonymous classes as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewClosure` sniff to detect anonymous functions as introduced in PHP 5.3. Fixes [#35](https://github.com/PHPCompatibility/PHPCompatibility/issues/35) +- :star2: New `NewFunctionParameters` sniff to detect use of new parameters in build-in PHP functions. Initially only sniffing for the new PHP 7.0 function parameters and the new PHP 5.3+ `before_needle` parameter for the `strstr()` function. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110), [#112](https://github.com/PHPCompatibility/PHPCompatibility/pull/112). Fixes [#27](https://github.com/PHPCompatibility/PHPCompatibility/issues/27). +- :star2: New `NewGroupUseDeclarations` sniff to detect group use declarations as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewScalarReturnTypeDeclarations` sniff to detect scalar return type hints as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `NewScalarTypeDeclarations` sniff to detect scalar function parameter type hints as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `RemovedFunctionParameters` sniff to detect use of removed parameters in build-in PHP functions. Initially only sniffing for the function parameters removed in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star2: New `RemovedGlobalVariables` sniff to detect the PHP 7.0 removed `$HTTP_RAW_POST_DATA` superglobal. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `DeprecatedFunctions` sniff: detection of the PHP 5.4 deprecated OCI8 functions. [#93](https://github.com/PHPCompatibility/PHPCompatibility/pull/93) +- :star: `ForbiddenNamesAsInvokedFunctions` sniff: recognize PHP 5.5 `finally` as a reserved keywords when invoked as a function. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `NewKeywords` sniff: detection of the use of the PHP 5.1+ `__halt_compiler` keyword. Fixes [#50](https://github.com/PHPCompatibility/PHPCompatibility/issues/50). +- :star: `NewKeywords` sniff: detection of the PHP 5.3+ `nowdoc` syntax. Fixes [#48](https://github.com/PHPCompatibility/PHPCompatibility/issues/48). +- :star: `NewKeywords` sniff: detection of the use of the `const` keyword outside of a class for PHP < 5.3. Fixes [#50](https://github.com/PHPCompatibility/PHPCompatibility/issues/50). +- :star: `DeprecatedFunctions` sniff: recognize PHP 7.0 deprecated and removed functions. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `DeprecatedIniDirectives` sniff: recognize PHP 7.0 removed ini directives. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `ForbiddenNamesAsInvokedFunctions` sniff: recognize new PHP 7.0 reserved keywords when invoked as functions. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `ForbiddenNames` sniff: recognize new PHP 7.0 reserved keywords. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `NewFunctions` sniff: recognize new functions as introduced in PHP 7.0. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `NewLanguageConstructs` sniff: recognize new PHP 7.0 `<=>` "spaceship" and `??` null coalescing operators. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :star: `RemovedExtensions` sniff: recognize PHP 7.0 removed `ereg`, `mssql`, `mysql` and `sybase_ct` extensions. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :umbrella: Additional unit tests for the `NewLanguageConstructs` sniff. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :books: Readme: New section containing information about the use of the `testVersion` config variable. +- :books: Readme: Sponsor credits. + +### Changed +- :pushpin: The `DeprecatedIniDirectives` sniff used to always throw an `warning`. Now it will throw an `error` when a removed ini directive is used. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110). +- :pushpin: The `DeprecatedNewReference` sniff will now throw an error when the `testVersion` includes PHP 7.0 or higher. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :pushpin: The `ForbiddenNames` sniff now supports detection of reserved keywords when used in combination with PHP 7 anonymous classes. [#108](https://github.com/PHPCompatibility/PHPCompatibility/pull/108), [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110). +- :pushpin: The `PregReplaceEModifier` sniff will now throw an error when the `testVersion` includes PHP 7.0 or higher. [#110](https://github.com/PHPCompatibility/PHPCompatibility/pull/110) +- :pencil2: `NewKeywords` sniff: clarified the error message text for the `use` keyword. Fixes [#46](https://github.com/PHPCompatibility/PHPCompatibility/issues/46). +- :recycle: Minor refactor of the `testVersion` related utility functions. [#98](https://github.com/PHPCompatibility/PHPCompatibility/pull/98) +- :wrench: Add autoload to the `composer.json` file. [#96](https://github.com/PHPCompatibility/PHPCompatibility/pull/96) Fixes [#67](https://github.com/PHPCompatibility/PHPCompatibility/issues/67). +- :wrench: Minor other updates to the `composer.json` file. [#75](https://github.com/PHPCompatibility/PHPCompatibility/pull/75) +- :wrench: Improved creation of the code coverage reports needed by coveralls via Travis. +- :green_heart: The sniffs are now also tested against PHP 7.0 for consistent results. + +### Fixed +- :bug: The `ForbiddenCallTimePassByReference` sniff was throwing `Undefined index` notices when used in combination with PHPCS 2.2.0. [#100](https://github.com/PHPCompatibility/PHPCompatibility/pull/100). Fixes [#42](https://github.com/PHPCompatibility/PHPCompatibility/issues/42). +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff would incorrectly throw an error if the `throw` keyword was used with parenthesis. Fixes [#118](https://github.com/PHPCompatibility/PHPCompatibility/issues/118). +- :bug: The `PregReplaceEModifier` sniff incorrectly identified `e`'s in the pattern as the `e` modifier when using `{}` bracket delimiters for the regex. [#94](https://github.com/PHPCompatibility/PHPCompatibility/pull/94) +- :bug: The `RemovedExtensions` sniff was throwing an `error` instead of a `warning` for deprecated, but not (yet) removed extensions. Fixes [#62](https://github.com/PHPCompatibility/PHPCompatibility/issues/62). + +### Credits +Thanks go out to AlexMiroshnikov, [Chris Abernethy], [dgudgeon], [djaenecke], [Eugene Maslovich], [Ken Guest], Koen Eelen, [Komarov Alexey], [Mark Clements] and [Remko van Bezooijen] for their contributions to this version. :clap: + + +## [5.6] - 2015-09-14 + +See all related issues and PRs in the [5.6 milestone]. + +### Added +- :star2: New: `NewLanguageConstructs` sniff. The initial version of this sniff checks for the PHP 5.6 `**` power operator and the `**=` power assignment operator. [#87](https://github.com/PHPCompatibility/PHPCompatibility/pull/87). Fixes [#60](https://github.com/PHPCompatibility/PHPCompatibility/issues/60). +- :star2: New: `ParameterShadowSuperGlobals` sniff which covers the PHP 5.4 change _Parameter names that shadow super globals now cause a fatal error.`_. [#74](https://github.com/PHPCompatibility/PHPCompatibility/pull/74) +- :star2: New: `PregReplaceEModifier` sniff which detects usage of the `e` modifier in literal regular expressions used with `preg_replace()`. The `e` modifier will not (yet) be detected when the regex passed is a variable or constant. [#81](https://github.com/PHPCompatibility/PHPCompatibility/pull/81), [#84](https://github.com/PHPCompatibility/PHPCompatibility/pull/84). Fixes [#71](https://github.com/PHPCompatibility/PHPCompatibility/issues/71), [#83](https://github.com/PHPCompatibility/PHPCompatibility/issues/83). +- :star: `DeprecatedIniDirectives` sniff: PHP 5.6 deprecated ini directives. +- :star: `NewKeywords` sniff: detection of the `goto` keyword introduced in PHP 5.3 and the `callable` keyword introduced in PHP 5.4. [#57](https://github.com/PHPCompatibility/PHPCompatibility/pull/57) +- :recycle: `PHPCompatibility_Sniff` base class initially containing the `supportsAbove()` and `supportsBelow()` utility methods. (Nearly) All sniffs now extend this base class and use these methods to determine whether or not violations should be reported for a set `testVersion`. [#77](https://github.com/PHPCompatibility/PHPCompatibility/pull/77) +- :books: Readme: Composer installation instructions. [#32](https://github.com/PHPCompatibility/PHPCompatibility/pull/32), [#61](https://github.com/PHPCompatibility/PHPCompatibility/pull/61) +- :wrench: `.gitignore` to ignore vendor and IDE related directories. [#78](https://github.com/PHPCompatibility/PHPCompatibility/pull/78) +- :green_heart: Code coverage checking via coveralls. + +### Changed +- :twisted_rightwards_arrows: The check for the `\` namespace separator has been moved from the `NewKeywords` sniff to the `NewLanguageConstructs` sniff. [#88](https://github.com/PHPCompatibility/PHPCompatibility/pull/88) +- :pencil2: `DeprecatedIniDirectives` sniff: minor change in the sniff error message text. +- :pencil2: `DeprecatedFunctions` sniff: minor change in the sniff error message text. +- :wrench: Minor updates to the `composer.json` file. [#31](https://github.com/PHPCompatibility/PHPCompatibility/pull/31), [34](https://github.com/PHPCompatibility/PHPCompatibility/pull/34), [#70](https://github.com/PHPCompatibility/PHPCompatibility/pull/70) +- :wrench: Tests: The unit tests can now be run without configuration. +- :wrench: Tests: Skipped unit tests will now be annotated as such. [#85](https://github.com/PHPCompatibility/PHPCompatibility/pull/85) +- :green_heart: The sniffs are now also tested against PHP 5.6 for consistent results. +- :green_heart: The sniffs are now also tested against PHPCS 2.0+. +- :green_heart: The sniffs are now tested using the new container-based infrastructure in Travis CI. [#37](https://github.com/PHPCompatibility/PHPCompatibility/pull/37) + +### Fixed +- :bug: The `ForbiddenCallTimePassByReference` sniff was throwing false positives when a bitwise and `&` was used in combination with class constants and class properties within function calls. [#44](https://github.com/PHPCompatibility/PHPCompatibility/pull/44). Fixes [#39](https://github.com/PHPCompatibility/PHPCompatibility/issues/39). +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff was throwing false positives in certain cases when a comment separated a `try` from the `catch` block. [#29](https://github.com/PHPCompatibility/PHPCompatibility/pull/29) +- :bug: The `ForbiddenNamesAsInvokedFunctions` sniff was incorrectly reporting `instanceof` as being introduced in PHP 5.4 while it has been around since PHP 5.0. [#80](https://github.com/PHPCompatibility/PHPCompatibility/pull/80) +- :white_check_mark: Compatibility with PHPCS 2.0 - 2.3. [#63](https://github.com/PHPCompatibility/PHPCompatibility/pull/63), [#65](https://github.com/PHPCompatibility/PHPCompatibility/pull/65) + +### Credits +Thanks go out to Daniel Jänecke, [Declan Kelly], [Dominic], [Jaap van Otterdijk], [Marin Crnkovic], [Mark Clements], [Nick Pack], [Oliver Klee], [Rowan Collins] and [Sam Van der Borght] for their contributions to this version. :clap: + + +## 5.5 - 2014-04-04 + +First tagged release. + +See all related issues and PRs in the [5.5 milestone]. + + + +[Unreleased]: https://github.com/PHPCompatibility/PHPCompatibility/compare/master...HEAD +[9.3.5]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.4...9.3.5 +[9.3.4]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.3...9.3.4 +[9.3.3]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.2...9.3.3 +[9.3.2]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.1...9.3.2 +[9.3.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.3.0...9.3.1 +[9.3.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.2.0...9.3.0 +[9.2.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.1.1...9.2.0 +[9.1.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.1.0...9.1.1 +[9.1.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/9.0.0...9.1.0 +[9.0.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.2.0...9.0.0 +[8.2.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.1.0...8.2.0 +[8.1.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.0.1...8.1.0 +[8.0.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/8.0.0...8.0.1 +[8.0.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.5...8.0.0 +[7.1.5]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.4...7.1.5 +[7.1.4]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.3...7.1.4 +[7.1.3]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.2...7.1.3 +[7.1.2]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.1...7.1.2 +[7.1.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.1.0...7.1.1 +[7.1.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.8...7.1.0 +[7.0.8]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.7...7.0.8 +[7.0.7]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.6...7.0.7 +[7.0.6]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.5...7.0.6 +[7.0.5]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.4...7.0.5 +[7.0.4]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.3...7.0.4 +[7.0.3]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.2...7.0.3 +[7.0.2]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0.1...7.0.2 +[7.0.1]: https://github.com/PHPCompatibility/PHPCompatibility/compare/7.0...7.0.1 +[7.0]: https://github.com/PHPCompatibility/PHPCompatibility/compare/5.6...7.0 +[5.6]: https://github.com/PHPCompatibility/PHPCompatibility/compare/5.5...5.6 + +[9.3.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/34 +[9.3.4 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/33 +[9.3.3 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/32 +[9.3.2 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/31 +[9.3.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/30 +[9.3.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/29 +[9.2.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/28 +[9.1.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/27 +[9.1.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/25 +[9.0.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/24 +[8.2.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/22 +[8.1.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/21 +[8.0.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/20 +[8.0.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/19 +[7.1.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/17 +[7.1.4 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/15 +[7.1.3 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/14 +[7.1.2 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/13 +[7.1.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/12 +[7.1.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/11 +[7.0.8 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/10 +[7.0.7 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/9 +[7.0.6 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/8 +[7.0.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/7 +[7.0.4 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/6 +[7.0.3 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/5 +[7.0.2 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/4 +[7.0.1 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/3 +[7.0 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/2 +[5.6 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/1 +[5.5 milestone]: https://github.com/PHPCompatibility/PHPCompatibility/milestone/16 + +[Arthur Edamov]: https://github.com/edamov +[Chris Abernethy]: https://github.com/cabernet-zerve +[Declan Kelly]: https://github.com/declank +[dgudgeon]: https://github.com/dgudgeon +[djaenecke]: https://github.com/djaenecke +[Dominic]: https://github.com/dol +[Eugene Maslovich]: https://github.com/ehpc +[Gary Jones]: https://github.com/GaryJones +[Jaap van Otterdijk]: https://github.com/jaapio +[Jason Stallings]: https://github.com/octalmage +[Jonathan Champ]: https://github.com/jrchamp +[Jonathan Van Belle]: https://github.com/Grummfy +[Juliette Reinders Folmer]: https://github.com/jrfnl +[Ken Guest]: https://github.com/kenguest +[Komarov Alexey]: https://github.com/erdraug +[Marin Crnkovic]: https://github.com/anorgan +[Mark Clements]: https://github.com/MarkMaldaba +[Michael Babker]: https://github.com/mbabker +[Nick Pack]: https://github.com/nickpack +[Nikhil]: https://github.com/Nikschavan +[Oliver Klee]: https://github.com/oliverklee +[Remko van Bezooijen]: https://github.com/emkookmer +[Rowan Collins]: https://github.com/IMSoP +[Ryan Neufeld]: https://github.com/ryanneufeld +[Sam Van der Borght]: https://github.com/samvdb +[Sergii Bondarenko]: https://github.com/BR0kEN- +[Tadas Juozapaitis]: https://github.com/kasp3r +[Tim Millwood]: https://github.com/timmillwood +[William Entriken]: https://github.com/fulldecent +[Yılmaz]: https://github.com/edigu +[Yoshiaki Yoshida]: https://github.com/kakakakakku diff --git a/kirki-composer/phpcompatibility/php-compatibility/LICENSE b/kirki-composer/phpcompatibility/php-compatibility/LICENSE new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/LICENSE @@ -0,0 +1,165 @@ + 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. diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCSAliases.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCSAliases.php new file mode 100644 index 000000000..97591a3ff --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCSAliases.php @@ -0,0 +1,73 @@ +` ruleset directive. + * + * {@internal The PHPCS file have been reorganized in PHPCS 3.x, quite + * a few "old" classes have been split and spread out over several "new" + * classes. In other words, this will only work for a limited number + * of classes.} + * + * {@internal The `class_exists` wrappers are needed to play nice with other + * external PHPCS standards creating cross-version compatibility in the same + * manner.} + */ +if (defined('PHPCOMPATIBILITY_PHPCS_ALIASES_SET') === false) { + if (interface_exists('\PHP_CodeSniffer_Sniff') === false) { + class_alias('PHP_CodeSniffer\Sniffs\Sniff', '\PHP_CodeSniffer_Sniff'); + } + if (class_exists('\PHP_CodeSniffer_File') === false) { + class_alias('PHP_CodeSniffer\Files\File', '\PHP_CodeSniffer_File'); + } + if (class_exists('\PHP_CodeSniffer_Tokens') === false) { + class_alias('PHP_CodeSniffer\Util\Tokens', '\PHP_CodeSniffer_Tokens'); + } + if (class_exists('\PHP_CodeSniffer_Exception') === false) { + class_alias('PHP_CodeSniffer\Exceptions\RuntimeException', '\PHP_CodeSniffer_Exception'); + } + if (class_exists('\PHP_CodeSniffer_Standards_AbstractScopeSniff') === false) { + class_alias('PHP_CodeSniffer\Sniffs\AbstractScopeSniff', '\PHP_CodeSniffer_Standards_AbstractScopeSniff'); + } + if (class_exists('\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff') === false) { + class_alias('PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', '\Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff'); + } + + define('PHPCOMPATIBILITY_PHPCS_ALIASES_SET', true); + + /* + * Register an autoloader. + * + * {@internal When `installed_paths` is set via the ruleset, this autoloader + * is needed to run the sniffs. + * Upstream issue: {@link https://github.com/squizlabs/PHP_CodeSniffer/issues/1591} } + * + * @since 8.0.0 + */ + spl_autoload_register(function ($class) { + // Only try & load our own classes. + if (stripos($class, 'PHPCompatibility') !== 0) { + return; + } + + $file = realpath(__DIR__) . DIRECTORY_SEPARATOR . strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; + + if (file_exists($file)) { + include_once $file; + } + }); +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php new file mode 100644 index 000000000..95245b6a3 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractComplexVersionSniff.php @@ -0,0 +1,147 @@ +getItemArray($itemInfo); + $errorInfo = $this->getErrorInfo($itemArray, $itemInfo); + + if ($this->shouldThrowError($errorInfo) === true) { + $this->addError($phpcsFile, $stackPtr, $itemInfo, $errorInfo); + } + } + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + abstract protected function shouldThrowError(array $errorInfo); + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array(); + } + + + /** + * Retrieve a subset of an item array containing only the array keys which + * contain PHP version information. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about an item. + * + * @return array Array with only the version information. + */ + protected function getVersionArray(array $itemArray) + { + return array_diff_key($itemArray, array_flip($this->getNonVersionArrayKeys())); + } + + + /** + * Get the item name to be used for the creation of the error code and in the error message. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Detail information about an item. + * + * @return string + */ + protected function getItemName(array $itemInfo, array $errorInfo) + { + return $itemInfo['name']; + } + + + /** + * Get the error message template for a specific sniff. + * + * @since 7.1.0 + * + * @return string + */ + abstract protected function getErrorMsgTemplate(); + + + /** + * Allow for concrete child classes to filter the error message before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + return $error; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + return $data; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php new file mode 100644 index 000000000..6db8cd086 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractFunctionCallParameterSniff.php @@ -0,0 +1,193 @@ + true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_NEW => true, + \T_CONST => true, + \T_USE => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->targetFunctions = $this->arrayKeysToLowercase($this->targetFunctions); + + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->bowOutEarly() === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->targetFunctions[$functionLc]) === false) { + return; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($this->isMethod === true) { + if ($tokens[$prevNonEmpty]['code'] !== \T_DOUBLE_COLON + && $tokens[$prevNonEmpty]['code'] !== \T_OBJECT_OPERATOR + ) { + // Not a call to a PHP method. + return; + } + } else { + if (isset($this->ignoreTokens[$tokens[$prevNonEmpty]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + if ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR + && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING + ) { + // Namespaced function. + return; + } + } + + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + + if (empty($parameters)) { + return $this->processNoParameters($phpcsFile, $stackPtr, $function); + } else { + return $this->processParameters($phpcsFile, $stackPtr, $function, $parameters); + } + } + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * If the check done in a child class is not specific to one PHP version, + * this function should return `false`. + * + * @return bool + */ + abstract protected function bowOutEarly(); + + + /** + * Process the parameters of a matched function. + * + * This method has to be made concrete in child classes. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + abstract public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters); + + + /** + * Process the function if no parameters were found. + * + * Defaults to doing nothing. Can be overloaded in child classes to handle functions + * were parameters are expected, but none found. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processNoParameters(File $phpcsFile, $stackPtr, $functionName) + { + return; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php new file mode 100644 index 000000000..25406fda0 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractNewFeatureSniff.php @@ -0,0 +1,115 @@ + '', + 'error' => true, + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $present) { + if ($errorInfo['not_in_version'] === '' && $present === false + && $this->supportsBelow($version) === true + ) { + $errorInfo['not_in_version'] = $version; + } + } + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return '%s is not present in PHP version %s or earlier'; + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $itemName = $this->getItemName($itemInfo, $errorInfo); + $error = $this->getErrorMsgTemplate(); + + $errorCode = $this->stringToErrorCode($itemName) . 'Found'; + $data = array( + $itemName, + $errorInfo['not_in_version'], + ); + + $error = $this->filterErrorMsg($error, $itemInfo, $errorInfo); + $data = $this->filterErrorData($data, $itemInfo, $errorInfo); + + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php new file mode 100644 index 000000000..94103922e --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/AbstractRemovedFeatureSniff.php @@ -0,0 +1,156 @@ + '', + 'removed' => '', + 'alternative' => '', + 'error' => false, + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $removed) { + if ($this->supportsAbove($version) === true) { + if ($removed === true && $errorInfo['removed'] === '') { + $errorInfo['removed'] = $version; + $errorInfo['error'] = true; + } elseif ($errorInfo['deprecated'] === '') { + $errorInfo['deprecated'] = $version; + } + } + } + } + + if (isset($itemArray['alternative']) === true) { + $errorInfo['alternative'] = $itemArray['alternative']; + } + + return $errorInfo; + } + + + /** + * Get the error message template for suggesting an alternative for a specific sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getAlternativeOptionTemplate() + { + return '; Use %s instead'; + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $itemName = $this->getItemName($itemInfo, $errorInfo); + $error = $this->getErrorMsgTemplate(); + + $errorCode = $this->stringToErrorCode($itemName); + $data = array($itemName); + + if ($errorInfo['deprecated'] !== '') { + $error .= 'deprecated since PHP %s and '; + $errorCode .= 'Deprecated'; + $data[] = $errorInfo['deprecated']; + } + + if ($errorInfo['removed'] !== '') { + $error .= 'removed since PHP %s and '; + $errorCode .= 'Removed'; + $data[] = $errorInfo['removed']; + } + + // Remove the last 'and' from the message. + $error = substr($error, 0, (\strlen($error) - 5)); + + if ($errorInfo['alternative'] !== '') { + $error .= $this->getAlternativeOptionTemplate(); + $data[] = $errorInfo['alternative']; + } + + $error = $this->filterErrorMsg($error, $itemInfo, $errorInfo); + $data = $this->filterErrorData($data, $itemInfo, $errorInfo); + + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php new file mode 100644 index 000000000..f5f63bbfb --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ComplexVersionInterface.php @@ -0,0 +1,84 @@ +config; + if (isset($config->{$key})) { + return $config->{$key}; + } + } else { + // PHPCS 2.x. + $config = $phpcsFile->phpcs->cli->getCommandLineValues(); + if (isset($config[$key])) { + return $config[$key]; + } + } + + return null; + } + + + /** + * Returns the position of the first non-whitespace token in a statement. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1. + * + * Once the minimum supported PHPCS version for this standard goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findStartOfStatement($start, $ignore)` calls. + * + * Last synced with PHPCS version: PHPCS 3.3.2 at commit 6ad28354c04b364c3c71a34e4a18b629cc3b231e} + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $start The position to start searching from in the token stack. + * @param int|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public static function findStartOfStatement(File $phpcsFile, $start, $ignore = null) + { + if (version_compare(self::getVersion(), '2.7.1', '>=') === true) { + return $phpcsFile->findStartOfStatement($start, $ignore); + } + + $tokens = $phpcsFile->getTokens(); + $endTokens = Tokens::$blockOpeners; + + $endTokens[\T_COLON] = true; + $endTokens[\T_COMMA] = true; + $endTokens[\T_DOUBLE_ARROW] = true; + $endTokens[\T_SEMICOLON] = true; + $endTokens[\T_OPEN_TAG] = true; + $endTokens[\T_CLOSE_TAG] = true; + $endTokens[\T_OPEN_SHORT_ARRAY] = true; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + $lastNotEmpty = $start; + + for ($i = $start; $i >= 0; $i--) { + if (isset($endTokens[$tokens[$i]['code']]) === true) { + // Found the end of the previous statement. + return $lastNotEmpty; + } + + if (isset($tokens[$i]['scope_opener']) === true + && $i === $tokens[$i]['scope_closer'] + ) { + // Found the end of the previous scope block. + return $lastNotEmpty; + } + + // Skip nested statements. + if (isset($tokens[$i]['bracket_opener']) === true + && $i === $tokens[$i]['bracket_closer'] + ) { + $i = $tokens[$i]['bracket_opener']; + } elseif (isset($tokens[$i]['parenthesis_opener']) === true + && $i === $tokens[$i]['parenthesis_closer'] + ) { + $i = $tokens[$i]['parenthesis_opener']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return 0; + } + + + /** + * Returns the position of the last non-whitespace token in a statement. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1 and 3.3.0. + * + * Once the minimum supported PHPCS version for this standard goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findEndOfStatement($start, $ignore)` calls. + * + * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit f5d899dcb5c534a1c3cca34668624517856ba823} + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $start The position to start searching from in the token stack. + * @param int|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public static function findEndOfStatement(File $phpcsFile, $start, $ignore = null) + { + if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { + return $phpcsFile->findEndOfStatement($start, $ignore); + } + + $tokens = $phpcsFile->getTokens(); + $endTokens = array( + \T_COLON => true, + \T_COMMA => true, + \T_DOUBLE_ARROW => true, + \T_SEMICOLON => true, + \T_CLOSE_PARENTHESIS => true, + \T_CLOSE_SQUARE_BRACKET => true, + \T_CLOSE_CURLY_BRACKET => true, + \T_CLOSE_SHORT_ARRAY => true, + \T_OPEN_TAG => true, + \T_CLOSE_TAG => true, + ); + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + $lastNotEmpty = $start; + + for ($i = $start; $i < $phpcsFile->numTokens; $i++) { + if ($i !== $start && isset($endTokens[$tokens[$i]['code']]) === true) { + // Found the end of the statement. + if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS + || $tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET + || $tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET + || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY + || $tokens[$i]['code'] === \T_OPEN_TAG + || $tokens[$i]['code'] === \T_CLOSE_TAG + ) { + return $lastNotEmpty; + } + + return $i; + } + + // Skip nested statements. + if (isset($tokens[$i]['scope_closer']) === true + && ($i === $tokens[$i]['scope_opener'] + || $i === $tokens[$i]['scope_condition']) + ) { + if ($i === $start && isset(Tokens::$scopeOpeners[$tokens[$i]['code']]) === true) { + return $tokens[$i]['scope_closer']; + } + + $i = $tokens[$i]['scope_closer']; + } elseif (isset($tokens[$i]['bracket_closer']) === true + && $i === $tokens[$i]['bracket_opener'] + ) { + $i = $tokens[$i]['bracket_closer']; + } elseif (isset($tokens[$i]['parenthesis_closer']) === true + && $i === $tokens[$i]['parenthesis_opener'] + ) { + $i = $tokens[$i]['parenthesis_closer']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return ($phpcsFile->numTokens - 1); + } + + + /** + * Returns the name of the class that the specified class extends + * (works for classes, anonymous classes and interfaces). + * + * Returns FALSE on error or if there is no extended class name. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class, but with some improvements which have been introduced in + * PHPCS 2.8.0. + * {@link https://github.com/squizlabs/PHP_CodeSniffer/commit/0011d448119d4c568e3ac1f825ae78815bf2cc34}. + * + * Once the minimum supported PHPCS version for this standard goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findExtendedClassName($stackPtr)` calls. + * + * Last synced with PHPCS version: PHPCS 3.1.0-alpha at commit a9efcc9b0703f3f9f4a900623d4e97128a6aafc6} + * + * @since 7.1.4 + * @since 8.2.0 Moved from the `Sniff` class to this class. + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position of the class token in the stack. + * + * @return string|false + */ + public static function findExtendedClassName(File $phpcsFile, $stackPtr) + { + if (version_compare(self::getVersion(), '3.1.0', '>=') === true) { + return $phpcsFile->findExtendedClassName($stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_CLASS + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' + && $tokens[$stackPtr]['type'] !== 'T_INTERFACE' + ) { + return false; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classCloserIndex = $tokens[$stackPtr]['scope_closer']; + $extendsIndex = $phpcsFile->findNext(\T_EXTENDS, $stackPtr, $classCloserIndex); + if ($extendsIndex === false) { + return false; + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_WHITESPACE, + ); + + $end = $phpcsFile->findNext($find, ($extendsIndex + 1), $classCloserIndex, true); + $name = $phpcsFile->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } + + return $name; + } + + + /** + * Returns the name(s) of the interface(s) that the specified class implements. + * + * Returns FALSE on error or if there are no implemented interface names. + * + * {@internal Duplicate of same method as introduced in PHPCS 2.7. + * This method also includes an improvement we use which was only introduced + * in PHPCS 2.8.0, so only defer to upstream for higher versions. + * Once the minimum supported PHPCS version for this sniff library goes beyond + * that, this method can be removed and calls to it replaced with + * `$phpcsFile->findImplementedInterfaceNames($stackPtr)` calls.} + * + * @since 7.0.3 + * @since 8.2.0 Moved from the `Sniff` class to this class. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the class token. + * + * @return array|false + */ + public static function findImplementedInterfaceNames(File $phpcsFile, $stackPtr) + { + if (version_compare(self::getVersion(), '2.7.1', '>') === true) { + return $phpcsFile->findImplementedInterfaceNames($stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_CLASS + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' + ) { + return false; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classOpenerIndex = $tokens[$stackPtr]['scope_opener']; + $implementsIndex = $phpcsFile->findNext(\T_IMPLEMENTS, $stackPtr, $classOpenerIndex); + if ($implementsIndex === false) { + return false; + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_WHITESPACE, + \T_COMMA, + ); + + $end = $phpcsFile->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); + $name = $phpcsFile->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } else { + $names = explode(',', $name); + $names = array_map('trim', $names); + return $names; + } + } + + + /** + * Returns the method parameters for the specified function token. + * + * Each parameter is in the following format: + * + * + * 0 => array( + * 'name' => '$var', // The variable name. + * 'token' => integer, // The stack pointer to the variable name. + * 'content' => string, // The full content of the variable definition. + * 'pass_by_reference' => boolean, // Is the variable passed by reference? + * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? + * 'type_hint' => string, // The type hint for the variable. + * 'type_hint_token' => integer, // The stack pointer to the type hint + * // or false if there is no type hint. + * 'nullable_type' => boolean, // Is the variable using a nullable type? + * ) + * + * + * Parameters with default values have an additional array index of + * 'default' with the value of the default as a string. + * + * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File` + * class. + * + * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit 53a28408d345044c0360c2c1b4a2aaebf4a3b8c9} + * + * @since 7.0.3 + * @since 8.2.0 Moved from the `Sniff` class to this class. + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * function token to acquire the + * parameters for. + * + * @return array|false + * @throws \PHP_CodeSniffer_Exception If the specified $stackPtr is not of + * type T_FUNCTION or T_CLOSURE. + */ + public static function getMethodParameters(File $phpcsFile, $stackPtr) + { + if (version_compare(self::getVersion(), '3.3.0', '>=') === true) { + return $phpcsFile->getMethodParameters($stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION + && $tokens[$stackPtr]['code'] !== \T_CLOSURE + ) { + throw new PHPCS_Exception('$stackPtr must be of type T_FUNCTION or T_CLOSURE'); + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $vars = array(); + $currVar = null; + $paramStart = ($opener + 1); + $defaultStart = null; + $paramCount = 0; + $passByReference = false; + $variableLength = false; + $typeHint = ''; + $typeHintToken = false; + $nullableType = false; + + for ($i = $paramStart; $i <= $closer; $i++) { + // Check to see if this token has a parenthesis or bracket opener. If it does + // it's likely to be an array which might have arguments in it. This + // could cause problems in our parsing below, so lets just skip to the + // end of it. + if (isset($tokens[$i]['parenthesis_opener']) === true) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $tokens[$i]['parenthesis_closer']) { + $i = ($tokens[$i]['parenthesis_closer'] + 1); + } + } + + if (isset($tokens[$i]['bracket_opener']) === true) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $tokens[$i]['bracket_closer']) { + $i = ($tokens[$i]['bracket_closer'] + 1); + } + } + + switch ($tokens[$i]['type']) { + case 'T_BITWISE_AND': + if ($defaultStart === null) { + $passByReference = true; + } + break; + case 'T_VARIABLE': + $currVar = $i; + break; + case 'T_ELLIPSIS': + $variableLength = true; + break; + case 'T_ARRAY_HINT': // Pre-PHPCS 3.3.0. + case 'T_CALLABLE': + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + break; + case 'T_SELF': + case 'T_PARENT': + case 'T_STATIC': + // Self and parent are valid, static invalid, but was probably intended as type hint. + if (isset($defaultStart) === false) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_STRING': + // This is a string, so it may be a type hint, but it could + // also be a constant used as a default value. + $prevComma = false; + for ($t = $i; $t >= $opener; $t--) { + if ($tokens[$t]['code'] === \T_COMMA) { + $prevComma = $t; + break; + } + } + + if ($prevComma !== false) { + $nextEquals = false; + for ($t = $prevComma; $t < $i; $t++) { + if ($tokens[$t]['code'] === \T_EQUAL) { + $nextEquals = $t; + break; + } + } + + if ($nextEquals !== false) { + break; + } + } + + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_NS_SEPARATOR': + // Part of a type hint or default value. + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_NULLABLE': + case 'T_INLINE_THEN': // Pre-PHPCS 2.8.0. + if ($defaultStart === null) { + $nullableType = true; + $typeHint .= $tokens[$i]['content']; + } + break; + case 'T_CLOSE_PARENTHESIS': + case 'T_COMMA': + // If it's null, then there must be no parameters for this + // method. + if ($currVar === null) { + break; + } + + $vars[$paramCount] = array(); + $vars[$paramCount]['token'] = $currVar; + $vars[$paramCount]['name'] = $tokens[$currVar]['content']; + $vars[$paramCount]['content'] = trim($phpcsFile->getTokensAsString($paramStart, ($i - $paramStart))); + + if ($defaultStart !== null) { + $vars[$paramCount]['default'] = trim( + $phpcsFile->getTokensAsString( + $defaultStart, + ($i - $defaultStart) + ) + ); + } + + $vars[$paramCount]['pass_by_reference'] = $passByReference; + $vars[$paramCount]['variable_length'] = $variableLength; + $vars[$paramCount]['type_hint'] = $typeHint; + $vars[$paramCount]['type_hint_token'] = $typeHintToken; + $vars[$paramCount]['nullable_type'] = $nullableType; + + // Reset the vars, as we are about to process the next parameter. + $defaultStart = null; + $paramStart = ($i + 1); + $passByReference = false; + $variableLength = false; + $typeHint = ''; + $typeHintToken = false; + $nullableType = false; + + $paramCount++; + break; + case 'T_EQUAL': + $defaultStart = ($i + 1); + break; + }//end switch + }//end for + + return $vars; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php new file mode 100644 index 000000000..38fb70928 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniff.php @@ -0,0 +1,2267 @@ +prop, self::prop and $var[]. + * + * @since 7.1.2 + * + * @var string + */ + const REGEX_COMPLEX_VARS = '`(?:(\{)?(?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(?:->\$?(?P>varname)|\[[^\]]+\]|::\$?(?P>varname)|\([^\)]*\))*(?(3)\}|)(?(2)\}|)(?(1)\}|)`'; + + /** + * List of superglobals as an array of strings. + * + * Used by the ForbiddenParameterShadowSuperGlobals and ForbiddenClosureUseVariableNames sniffs. + * + * @since 7.0.0 + * @since 7.1.4 Moved from the `ForbiddenParameterShadowSuperGlobals` sniff to the base `Sniff` class. + * + * @var array + */ + protected $superglobals = array( + '$GLOBALS' => true, + '$_SERVER' => true, + '$_GET' => true, + '$_POST' => true, + '$_FILES' => true, + '$_COOKIE' => true, + '$_SESSION' => true, + '$_REQUEST' => true, + '$_ENV' => true, + ); + + /** + * List of functions using hash algorithm as parameter (always the first parameter). + * + * Used by the new/removed hash algorithm sniffs. + * Key is the function name, value is the 1-based parameter position in the function call. + * + * @since 5.5 + * @since 7.0.7 Moved from the `RemovedHashAlgorithms` sniff to the base `Sniff` class. + * + * @var array + */ + protected $hashAlgoFunctions = array( + 'hash_file' => 1, + 'hash_hmac_file' => 1, + 'hash_hmac' => 1, + 'hash_init' => 1, + 'hash_pbkdf2' => 1, + 'hash' => 1, + ); + + + /** + * List of functions which take an ini directive as parameter (always the first parameter). + * + * Used by the new/removed ini directives sniffs. + * Key is the function name, value is the 1-based parameter position in the function call. + * + * @since 7.1.0 + * + * @var array + */ + protected $iniFunctions = array( + 'ini_get' => 1, + 'ini_set' => 1, + ); + + + /** + * Get the testVersion configuration variable. + * + * The testVersion configuration variable may be in any of the following formats: + * 1) Omitted/empty, in which case no version is specified. This effectively + * disables all the checks for new PHP features provided by this standard. + * 2) A single PHP version number, e.g. "5.4" in which case the standard checks that + * the code will run on that version of PHP (no deprecated features or newer + * features being used). + * 3) A range, e.g. "5.0-5.5", in which case the standard checks the code will run + * on all PHP versions in that range, and that it doesn't use any features that + * were deprecated by the final version in the list, or which were not available + * for the first version in the list. + * We accept ranges where one of the components is missing, e.g. "-5.6" means + * all versions up to PHP 5.6, and "7.0-" means all versions above PHP 7.0. + * PHP version numbers should always be in Major.Minor format. Both "5", "5.3.2" + * would be treated as invalid, and ignored. + * + * @since 7.0.0 + * @since 7.1.3 Now allows for partial ranges such as `5.2-`. + * + * @return array $arrTestVersions will hold an array containing min/max version + * of PHP that we are checking against (see above). If only a + * single version number is specified, then this is used as + * both the min and max. + * + * @throws \PHP_CodeSniffer_Exception If testVersion is invalid. + */ + private function getTestVersion() + { + static $arrTestVersions = array(); + + $default = array(null, null); + $testVersion = trim(PHPCSHelper::getConfigData('testVersion')); + + if (empty($testVersion) === false && isset($arrTestVersions[$testVersion]) === false) { + + $arrTestVersions[$testVersion] = $default; + + if (preg_match('`^\d+\.\d+$`', $testVersion)) { + $arrTestVersions[$testVersion] = array($testVersion, $testVersion); + return $arrTestVersions[$testVersion]; + } + + if (preg_match('`^(\d+\.\d+)?\s*-\s*(\d+\.\d+)?$`', $testVersion, $matches)) { + if (empty($matches[1]) === false || empty($matches[2]) === false) { + // If no lower-limit is set, we set the min version to 4.0. + // Whilst development focuses on PHP 5 and above, we also accept + // sniffs for PHP 4, so we include that as the minimum. + // (It makes no sense to support PHP 3 as this was effectively a + // different language). + $min = empty($matches[1]) ? '4.0' : $matches[1]; + + // If no upper-limit is set, we set the max version to 99.9. + $max = empty($matches[2]) ? '99.9' : $matches[2]; + + if (version_compare($min, $max, '>')) { + trigger_error( + "Invalid range in testVersion setting: '" . $testVersion . "'", + \E_USER_WARNING + ); + return $default; + } else { + $arrTestVersions[$testVersion] = array($min, $max); + return $arrTestVersions[$testVersion]; + } + } + } + + trigger_error( + "Invalid testVersion setting: '" . $testVersion . "'", + \E_USER_WARNING + ); + return $default; + } + + if (isset($arrTestVersions[$testVersion])) { + return $arrTestVersions[$testVersion]; + } + + return $default; + } + + + /** + * Check whether a specific PHP version is equal to or higher than the maximum + * supported PHP version as provided by the user in `testVersion`. + * + * Should be used when sniffing for *old* PHP features (deprecated/removed). + * + * @since 5.6 + * + * @param string $phpVersion A PHP version number in 'major.minor' format. + * + * @return bool True if testVersion has not been provided or if the PHP version + * is equal to or higher than the highest supported PHP version + * in testVersion. False otherwise. + */ + public function supportsAbove($phpVersion) + { + $testVersion = $this->getTestVersion(); + $testVersion = $testVersion[1]; + + if (\is_null($testVersion) + || version_compare($testVersion, $phpVersion) >= 0 + ) { + return true; + } else { + return false; + } + } + + + /** + * Check whether a specific PHP version is equal to or lower than the minimum + * supported PHP version as provided by the user in `testVersion`. + * + * Should be used when sniffing for *new* PHP features. + * + * @since 5.6 + * + * @param string $phpVersion A PHP version number in 'major.minor' format. + * + * @return bool True if the PHP version is equal to or lower than the lowest + * supported PHP version in testVersion. + * False otherwise or if no testVersion is provided. + */ + public function supportsBelow($phpVersion) + { + $testVersion = $this->getTestVersion(); + $testVersion = $testVersion[0]; + + if (\is_null($testVersion) === false + && version_compare($testVersion, $phpVersion) <= 0 + ) { + return true; + } else { + return false; + } + } + + + /** + * Add a PHPCS message to the output stack as either a warning or an error. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file the message applies to. + * @param string $message The message. + * @param int $stackPtr The position of the token + * the message relates to. + * @param bool $isError Whether to report the message as an + * 'error' or 'warning'. + * Defaults to true (error). + * @param string $code The error code for the message. + * Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * + * @return void + */ + public function addMessage(File $phpcsFile, $message, $stackPtr, $isError, $code = 'Found', $data = array()) + { + if ($isError === true) { + $phpcsFile->addError($message, $stackPtr, $code, $data); + } else { + $phpcsFile->addWarning($message, $stackPtr, $code, $data); + } + } + + + /** + * Convert an arbitrary string to an alphanumeric string with underscores. + * + * Pre-empt issues with arbitrary strings being used as error codes in XML and PHP. + * + * @since 7.1.0 + * + * @param string $baseString Arbitrary string. + * + * @return string + */ + public function stringToErrorCode($baseString) + { + return preg_replace('`[^a-z0-9_]`i', '_', strtolower($baseString)); + } + + + /** + * Strip quotes surrounding an arbitrary string. + * + * Intended for use with the contents of a T_CONSTANT_ENCAPSED_STRING / T_DOUBLE_QUOTED_STRING. + * + * @since 7.0.6 + * + * @param string $string The raw string. + * + * @return string String without quotes around it. + */ + public function stripQuotes($string) + { + return preg_replace('`^([\'"])(.*)\1$`Ds', '$2', $string); + } + + + /** + * Strip variables from an arbitrary double quoted string. + * + * Intended for use with the contents of a T_DOUBLE_QUOTED_STRING. + * + * @since 7.1.2 + * + * @param string $string The raw string. + * + * @return string String without variables in it. + */ + public function stripVariables($string) + { + if (strpos($string, '$') === false) { + return $string; + } + + return preg_replace(self::REGEX_COMPLEX_VARS, '', $string); + } + + + /** + * Make all top level array keys in an array lowercase. + * + * @since 7.1.0 + * + * @param array $array Initial array. + * + * @return array Same array, but with all lowercase top level keys. + */ + public function arrayKeysToLowercase($array) + { + return array_change_key_case($array, \CASE_LOWER); + } + + + /** + * Checks if a function call has parameters. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, it + * will detect whether the array has values or is empty. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/120 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/152 + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function doesFunctionCallHaveParameters(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // Is this one of the tokens this function handles ? + if (\in_array($tokens[$stackPtr]['code'], array(\T_STRING, \T_ARRAY, \T_OPEN_SHORT_ARRAY, \T_VARIABLE), true) === false) { + return false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + + // Deal with short array syntax. + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + return false; + } + + if ($nextNonEmpty === $tokens[$stackPtr]['bracket_closer']) { + // No parameters. + return false; + } else { + return true; + } + } + + // Deal with function calls & long arrays. + // Next non-empty token should be the open parenthesis. + if ($nextNonEmpty === false && $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + return false; + } + + if (isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false) { + return false; + } + + $closeParenthesis = $tokens[$nextNonEmpty]['parenthesis_closer']; + $nextNextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $nextNonEmpty + 1, $closeParenthesis + 1, true); + + if ($nextNextNonEmpty === $closeParenthesis) { + // No parameters. + return false; + } + + return true; + } + + + /** + * Count the number of parameters a function call has been passed. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will return the number of values in the array. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/111 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/114 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/151 + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return int + */ + public function getFunctionCallParameterCount(File $phpcsFile, $stackPtr) + { + if ($this->doesFunctionCallHaveParameters($phpcsFile, $stackPtr) === false) { + return 0; + } + + return \count($this->getFunctionCallParameters($phpcsFile, $stackPtr)); + } + + + /** + * Get information on all parameters passed to a function call. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Will return an multi-dimentional array with the start token pointer, end token + * pointer and raw parameter value for all parameters. Index will be 1-based. + * If no parameters are found, will return an empty array. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will tokenize the values / key/value pairs contained in the array call. + * + * @since 7.0.5 Split off from the `getFunctionCallParameterCount()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return array + */ + public function getFunctionCallParameters(File $phpcsFile, $stackPtr) + { + if ($this->doesFunctionCallHaveParameters($phpcsFile, $stackPtr) === false) { + return array(); + } + + // Ok, we know we have a T_STRING, T_VARIABLE, T_ARRAY or T_OPEN_SHORT_ARRAY with parameters + // and valid open & close brackets/parenthesis. + $tokens = $phpcsFile->getTokens(); + + // Mark the beginning and end tokens. + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + $opener = $stackPtr; + $closer = $tokens[$stackPtr]['bracket_closer']; + + $nestedParenthesisCount = 0; + + } else { + $opener = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + $closer = $tokens[$opener]['parenthesis_closer']; + + $nestedParenthesisCount = 1; + } + + // Which nesting level is the one we are interested in ? + if (isset($tokens[$opener]['nested_parenthesis'])) { + $nestedParenthesisCount += \count($tokens[$opener]['nested_parenthesis']); + } + + $parameters = array(); + $nextComma = $opener; + $paramStart = $opener + 1; + $cnt = 1; + while (($nextComma = $phpcsFile->findNext(array(\T_COMMA, $tokens[$closer]['code'], \T_OPEN_SHORT_ARRAY, \T_CLOSURE), $nextComma + 1, $closer + 1)) !== false) { + // Ignore anything within short array definition brackets. + if ($tokens[$nextComma]['type'] === 'T_OPEN_SHORT_ARRAY' + && (isset($tokens[$nextComma]['bracket_opener']) + && $tokens[$nextComma]['bracket_opener'] === $nextComma) + && isset($tokens[$nextComma]['bracket_closer']) + ) { + // Skip forward to the end of the short array definition. + $nextComma = $tokens[$nextComma]['bracket_closer']; + continue; + } + + // Skip past closures passed as function parameters. + if ($tokens[$nextComma]['type'] === 'T_CLOSURE' + && (isset($tokens[$nextComma]['scope_condition']) + && $tokens[$nextComma]['scope_condition'] === $nextComma) + && isset($tokens[$nextComma]['scope_closer']) + ) { + // Skip forward to the end of the closure declaration. + $nextComma = $tokens[$nextComma]['scope_closer']; + continue; + } + + // Ignore comma's at a lower nesting level. + if ($tokens[$nextComma]['type'] === 'T_COMMA' + && isset($tokens[$nextComma]['nested_parenthesis']) + && \count($tokens[$nextComma]['nested_parenthesis']) !== $nestedParenthesisCount + ) { + continue; + } + + // Ignore closing parenthesis/bracket if not 'ours'. + if ($tokens[$nextComma]['type'] === $tokens[$closer]['type'] && $nextComma !== $closer) { + continue; + } + + // Ok, we've reached the end of the parameter. + $parameters[$cnt]['start'] = $paramStart; + $parameters[$cnt]['end'] = $nextComma - 1; + $parameters[$cnt]['raw'] = trim($phpcsFile->getTokensAsString($paramStart, ($nextComma - $paramStart))); + + /* + * Check if there are more tokens before the closing parenthesis. + * Prevents code like the following from setting a third parameter: + * `functionCall( $param1, $param2, );`. + */ + $hasNextParam = $phpcsFile->findNext(Tokens::$emptyTokens, $nextComma + 1, $closer, true, null, true); + if ($hasNextParam === false) { + break; + } + + // Prepare for the next parameter. + $paramStart = $nextComma + 1; + $cnt++; + } + + return $parameters; + } + + + /** + * Get information on a specific parameter passed to a function call. + * + * Expects to be passed the T_STRING or T_VARIABLE stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Will return a array with the start token pointer, end token pointer and the raw value + * of the parameter at a specific offset. + * If the specified parameter is not found, will return false. + * + * @since 7.0.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * @param int $paramOffset The 1-based index position of the parameter to retrieve. + * + * @return array|false + */ + public function getFunctionCallParameter(File $phpcsFile, $stackPtr, $paramOffset) + { + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + + if (isset($parameters[$paramOffset]) === false) { + return false; + } else { + return $parameters[$paramOffset]; + } + } + + + /** + * Verify whether a token is within a scoped condition. + * + * If the optional $validScopes parameter has been passed, the function + * will check that the token has at least one condition which is of a + * type defined in $validScopes. + * + * @since 7.0.5 Largely split off from the `inClassScope()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * @param array|int $validScopes Optional. Array of valid scopes + * or int value of a valid scope. + * Pass the T_.. constant(s) for the + * desired scope to this parameter. + * + * @return bool Without the optional $scopeTypes: True if within a scope, false otherwise. + * If the $scopeTypes are set: True if *one* of the conditions is a + * valid scope, false otherwise. + */ + public function tokenHasScope(File $phpcsFile, $stackPtr, $validScopes = null) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // No conditions = no scope. + if (empty($tokens[$stackPtr]['conditions'])) { + return false; + } + + // Ok, there are conditions, do we have to check for specific ones ? + if (isset($validScopes) === false) { + return true; + } + + return $phpcsFile->hasCondition($stackPtr, $validScopes); + } + + + /** + * Verify whether a token is within a class scope. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * @param bool $strict Whether to strictly check for the T_CLASS + * scope or also accept interfaces and traits + * as scope. + * + * @return bool True if within class scope, false otherwise. + */ + public function inClassScope(File $phpcsFile, $stackPtr, $strict = true) + { + $validScopes = array(\T_CLASS); + if (\defined('T_ANON_CLASS') === true) { + $validScopes[] = \T_ANON_CLASS; + } + + if ($strict === false) { + $validScopes[] = \T_INTERFACE; + $validScopes[] = \T_TRAIT; + } + + return $phpcsFile->hasCondition($stackPtr, $validScopes); + } + + + /** + * Returns the fully qualified class name for a new class instantiation. + * + * Returns an empty string if the class name could not be reliably inferred. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_NEW token. + * + * @return string + */ + public function getFQClassNameFromNewToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + if ($tokens[$stackPtr]['code'] !== \T_NEW) { + return ''; + } + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if ($start === false) { + return ''; + } + + // Bow out if the next token is a variable as we don't know where it was defined. + if ($tokens[$start]['code'] === \T_VARIABLE) { + return ''; + } + + // Bow out if the next token is the class keyword. + if ($tokens[$start]['type'] === 'T_ANON_CLASS' || $tokens[$start]['code'] === \T_CLASS) { + return ''; + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_NAMESPACE, + \T_WHITESPACE, + ); + + $end = $phpcsFile->findNext($find, ($start + 1), null, true, null, true); + $className = $phpcsFile->getTokensAsString($start, ($end - $start)); + $className = trim($className); + + return $this->getFQName($phpcsFile, $stackPtr, $className); + } + + + /** + * Returns the fully qualified name of the class that the specified class extends. + * + * Returns an empty string if the class does not extend another class or if + * the class name could not be reliably inferred. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_CLASS token. + * + * @return string + */ + public function getFQExtendedClassName(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + if ($tokens[$stackPtr]['code'] !== \T_CLASS + && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS' + && $tokens[$stackPtr]['type'] !== 'T_INTERFACE' + ) { + return ''; + } + + $extends = PHPCSHelper::findExtendedClassName($phpcsFile, $stackPtr); + if (empty($extends) || \is_string($extends) === false) { + return ''; + } + + return $this->getFQName($phpcsFile, $stackPtr, $extends); + } + + + /** + * Returns the class name for the static usage of a class. + * This can be a call to a method, the use of a property or constant. + * + * Returns an empty string if the class name could not be reliably inferred. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_NEW token. + * + * @return string + */ + public function getFQClassNameFromDoubleColonToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + if ($tokens[$stackPtr]['code'] !== \T_DOUBLE_COLON) { + return ''; + } + + // Nothing to do if previous token is a variable as we don't know where it was defined. + if ($tokens[$stackPtr - 1]['code'] === \T_VARIABLE) { + return ''; + } + + // Nothing to do if 'parent' or 'static' as we don't know how far the class tree extends. + if (\in_array($tokens[$stackPtr - 1]['code'], array(\T_PARENT, \T_STATIC), true)) { + return ''; + } + + // Get the classname from the class declaration if self is used. + if ($tokens[$stackPtr - 1]['code'] === \T_SELF) { + $classDeclarationPtr = $phpcsFile->findPrevious(\T_CLASS, $stackPtr - 1); + if ($classDeclarationPtr === false) { + return ''; + } + $className = $phpcsFile->getDeclarationName($classDeclarationPtr); + return $this->getFQName($phpcsFile, $classDeclarationPtr, $className); + } + + $find = array( + \T_NS_SEPARATOR, + \T_STRING, + \T_NAMESPACE, + \T_WHITESPACE, + ); + + $start = $phpcsFile->findPrevious($find, $stackPtr - 1, null, true, null, true); + if ($start === false || isset($tokens[($start + 1)]) === false) { + return ''; + } + + $start = ($start + 1); + $className = $phpcsFile->getTokensAsString($start, ($stackPtr - $start)); + $className = trim($className); + + return $this->getFQName($phpcsFile, $stackPtr, $className); + } + + + /** + * Get the Fully Qualified name for a class/function/constant etc. + * + * Checks if a class/function/constant name is already fully qualified and + * if not, enrich it with the relevant namespace information. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * @param string $name The class / function / constant name. + * + * @return string + */ + public function getFQName(File $phpcsFile, $stackPtr, $name) + { + if (strpos($name, '\\') === 0) { + // Already fully qualified. + return $name; + } + + // Remove the namespace keyword if used. + if (strpos($name, 'namespace\\') === 0) { + $name = substr($name, 10); + } + + $namespace = $this->determineNamespace($phpcsFile, $stackPtr); + + if ($namespace === '') { + return '\\' . $name; + } else { + return '\\' . $namespace . '\\' . $name; + } + } + + + /** + * Is the class/function/constant name namespaced or global ? + * + * @since 7.0.3 + * + * @param string $FQName Fully Qualified name of a class, function etc. + * I.e. should always start with a `\`. + * + * @return bool True if namespaced, false if global. + * + * @throws \PHP_CodeSniffer_Exception If the name in the passed parameter + * is not fully qualified. + */ + public function isNamespaced($FQName) + { + if (strpos($FQName, '\\') !== 0) { + throw new PHPCS_Exception('$FQName must be a fully qualified name'); + } + + return (strpos(substr($FQName, 1), '\\') !== false); + } + + + /** + * Determine the namespace name an arbitrary token lives in. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The token position for which to determine the namespace. + * + * @return string Namespace name or empty string if it couldn't be determined or no namespace applies. + */ + public function determineNamespace(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return ''; + } + + // Check for scoped namespace {}. + if (empty($tokens[$stackPtr]['conditions']) === false) { + $namespacePtr = $phpcsFile->getCondition($stackPtr, \T_NAMESPACE); + if ($namespacePtr !== false) { + $namespace = $this->getDeclaredNamespaceName($phpcsFile, $namespacePtr); + if ($namespace !== false) { + return $namespace; + } + + // We are in a scoped namespace, but couldn't determine the name. Searching for a global namespace is futile. + return ''; + } + } + + /* + * Not in a scoped namespace, so let's see if we can find a non-scoped namespace instead. + * Keeping in mind that: + * - there can be multiple non-scoped namespaces in a file (bad practice, but it happens). + * - the namespace keyword can also be used as part of a function/method call and such. + * - that a non-named namespace resolves to the global namespace. + */ + $previousNSToken = $stackPtr; + $namespace = false; + do { + $previousNSToken = $phpcsFile->findPrevious(\T_NAMESPACE, ($previousNSToken - 1)); + + // Stop if we encounter a scoped namespace declaration as we already know we're not in one. + if (empty($tokens[$previousNSToken]['scope_condition']) === false && $tokens[$previousNSToken]['scope_condition'] === $previousNSToken) { + break; + } + + $namespace = $this->getDeclaredNamespaceName($phpcsFile, $previousNSToken); + + } while ($namespace === false && $previousNSToken !== false); + + // If we still haven't got a namespace, return an empty string. + if ($namespace === false) { + return ''; + } else { + return $namespace; + } + } + + /** + * Get the complete namespace name for a namespace declaration. + * + * For hierarchical namespaces, the name will be composed of several tokens, + * i.e. MyProject\Sub\Level which will be returned together as one string. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int|bool $stackPtr The position of a T_NAMESPACE token. + * + * @return string|false Namespace name or false if not a namespace declaration. + * Namespace name can be an empty string for global namespace declaration. + */ + public function getDeclaredNamespaceName(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if ($stackPtr === false || isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_NAMESPACE) { + return false; + } + + if ($tokens[($stackPtr + 1)]['code'] === \T_NS_SEPARATOR) { + // Not a namespace declaration, but use of, i.e. `namespace\someFunction();`. + return false; + } + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($tokens[$nextToken]['code'] === \T_OPEN_CURLY_BRACKET) { + /* + * Declaration for global namespace when using multiple namespaces in a file. + * I.e.: `namespace {}`. + */ + return ''; + } + + // Ok, this should be a namespace declaration, so get all the parts together. + $validTokens = array( + \T_STRING => true, + \T_NS_SEPARATOR => true, + \T_WHITESPACE => true, + ); + + $namespaceName = ''; + while (isset($validTokens[$tokens[$nextToken]['code']]) === true) { + $namespaceName .= trim($tokens[$nextToken]['content']); + $nextToken++; + } + + return $namespaceName; + } + + + /** + * Get the stack pointer for a return type token for a given function. + * + * Compatible layer for older PHPCS versions which don't recognize + * return type hints correctly. + * + * Expects to be passed T_RETURN_TYPE, T_FUNCTION or T_CLOSURE token. + * + * @since 7.1.2 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * + * @return int|false Stack pointer to the return type token or false if + * no return type was found or the passed token was + * not of the correct type. + */ + public function getReturnTypeHintToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (\defined('T_RETURN_TYPE') && $tokens[$stackPtr]['code'] === \T_RETURN_TYPE) { + return $stackPtr; + } + + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION && $tokens[$stackPtr]['code'] !== \T_CLOSURE) { + return false; + } + + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) { + return false; + } + + // Allow for interface and abstract method declarations. + $endOfFunctionDeclaration = null; + if (isset($tokens[$stackPtr]['scope_opener'])) { + $endOfFunctionDeclaration = $tokens[$stackPtr]['scope_opener']; + } else { + $nextSemiColon = $phpcsFile->findNext(\T_SEMICOLON, ($tokens[$stackPtr]['parenthesis_closer'] + 1), null, false, null, true); + if ($nextSemiColon !== false) { + $endOfFunctionDeclaration = $nextSemiColon; + } + } + + if (isset($endOfFunctionDeclaration) === false) { + return false; + } + + $hasColon = $phpcsFile->findNext( + array(\T_COLON, \T_INLINE_ELSE), + ($tokens[$stackPtr]['parenthesis_closer'] + 1), + $endOfFunctionDeclaration + ); + if ($hasColon === false) { + return false; + } + + /* + * - `self`, `parent` and `callable` are not being recognized as return types in PHPCS < 2.6.0. + * - Return types are not recognized at all in PHPCS < 2.4.0. + * - The T_RETURN_TYPE token is defined, but no longer in use since PHPCS 3.3.0+. + * The token will now be tokenized as T_STRING. + * - An `array` (return) type declaration was tokenized as `T_ARRAY_HINT` in PHPCS 2.3.3 - 3.2.3 + * to prevent confusing sniffs looking for array declarations. + * As of PHPCS 3.3.0 `array` as a type declaration will be tokenized as `T_STRING`. + */ + $unrecognizedTypes = array( + \T_CALLABLE, + \T_SELF, + \T_PARENT, + \T_ARRAY, // PHPCS < 2.4.0. + \T_STRING, + ); + + return $phpcsFile->findPrevious($unrecognizedTypes, ($endOfFunctionDeclaration - 1), $hasColon); + } + + + /** + * Get the complete return type declaration for a given function. + * + * Cross-version compatible way to retrieve the complete return type declaration. + * + * For a classname-based return type, PHPCS, as well as the Sniff::getReturnTypeHintToken() + * method will mark the classname as the return type token. + * This method will find preceeding namespaces and namespace separators and will return a + * string containing the qualified return type declaration. + * + * Expects to be passed a T_RETURN_TYPE token or the return value from a call to + * the Sniff::getReturnTypeHintToken() method. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the return type token. + * + * @return string The name of the return type token. + */ + public function getReturnTypeHintName(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // In older PHPCS versions, the nullable indicator will turn a return type colon into a T_INLINE_ELSE. + $colon = $phpcsFile->findPrevious(array(\T_COLON, \T_INLINE_ELSE, \T_FUNCTION, \T_CLOSE_PARENTHESIS), ($stackPtr - 1)); + if ($colon === false + || ($tokens[$colon]['code'] !== \T_COLON && $tokens[$colon]['code'] !== \T_INLINE_ELSE) + ) { + // Shouldn't happen, just in case. + return ''; + } + + $returnTypeHint = ''; + for ($i = ($colon + 1); $i <= $stackPtr; $i++) { + // As of PHPCS 3.3.0+, all tokens are tokenized as "normal", so T_CALLABLE, T_SELF etc are + // all possible, just exclude anything that's regarded as empty and the nullable indicator. + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']])) { + continue; + } + + if ($tokens[$i]['type'] === 'T_NULLABLE') { + continue; + } + + if (\defined('T_NULLABLE') === false && $tokens[$i]['code'] === \T_INLINE_THEN) { + // Old PHPCS. + continue; + } + + $returnTypeHint .= $tokens[$i]['content']; + } + + return $returnTypeHint; + } + + + /** + * Check whether a T_VARIABLE token is a class property declaration. + * + * Compatibility layer for PHPCS cross-version compatibility + * as PHPCS 2.4.0 - 2.7.1 does not have good enough support for + * anonymous classes. Along the same lines, the`getMemberProperties()` + * method does not support the `var` prefix. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * T_VARIABLE token to verify. + * + * @return bool + */ + public function isClassProperty(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]) === false || $tokens[$stackPtr]['code'] !== \T_VARIABLE) { + return false; + } + + // Note: interfaces can not declare properties. + $validScopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_TRAIT' => true, + ); + + $scopePtr = $this->validDirectScope($phpcsFile, $stackPtr, $validScopes); + if ($scopePtr !== false) { + // Make sure it's not a method parameter. + if (empty($tokens[$stackPtr]['nested_parenthesis']) === true) { + return true; + } else { + $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); + $deepestOpen = array_pop($parenthesis); + if ($deepestOpen < $scopePtr + || isset($tokens[$deepestOpen]['parenthesis_owner']) === false + || $tokens[$tokens[$deepestOpen]['parenthesis_owner']]['code'] !== \T_FUNCTION + ) { + return true; + } + } + } + + return false; + } + + + /** + * Check whether a T_CONST token is a class constant declaration. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * T_CONST token to verify. + * + * @return bool + */ + public function isClassConstant(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]) === false || $tokens[$stackPtr]['code'] !== \T_CONST) { + return false; + } + + // Note: traits can not declare constants. + $validScopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + ); + if ($this->validDirectScope($phpcsFile, $stackPtr, $validScopes) !== false) { + return true; + } + + return false; + } + + + /** + * Check whether the direct wrapping scope of a token is within a limited set of + * acceptable tokens. + * + * Used to check, for instance, if a T_CONST is a class constant. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position in the stack of the + * token to verify. + * @param array $validScopes Array of token types. + * Keys should be the token types in string + * format to allow for newer token types. + * Value is irrelevant. + * + * @return int|bool StackPtr to the scope if valid, false otherwise. + */ + protected function validDirectScope(File $phpcsFile, $stackPtr, $validScopes) + { + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + return false; + } + + /* + * Check only the direct wrapping scope of the token. + */ + $conditions = array_keys($tokens[$stackPtr]['conditions']); + $ptr = array_pop($conditions); + + if (isset($tokens[$ptr]) === false) { + return false; + } + + if (isset($validScopes[$tokens[$ptr]['type']]) === true) { + return $ptr; + } + + return false; + } + + + /** + * Get an array of just the type hints from a function declaration. + * + * Expects to be passed T_FUNCTION or T_CLOSURE token. + * + * Strips potential nullable indicator and potential global namespace + * indicator from the type hints before returning them. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token. + * + * @return array Array with type hints or an empty array if + * - the function does not have any parameters + * - no type hints were found + * - or the passed token was not of the correct type. + */ + public function getTypeHintsFromFunctionDeclaration(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] !== \T_FUNCTION && $tokens[$stackPtr]['code'] !== \T_CLOSURE) { + return array(); + } + + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($parameters) || \is_array($parameters) === false) { + return array(); + } + + $typeHints = array(); + + foreach ($parameters as $param) { + if ($param['type_hint'] === '') { + continue; + } + + // Strip off potential nullable indication. + $typeHint = ltrim($param['type_hint'], '?'); + + // Strip off potential (global) namespace indication. + $typeHint = ltrim($typeHint, '\\'); + + if ($typeHint !== '') { + $typeHints[] = $typeHint; + } + } + + return $typeHints; + } + + + /** + * Get the hash algorithm name from the parameter in a hash function call. + * + * @since 7.0.7 Logic was originally contained in the `RemovedHashAlgorithms` sniff. + * + * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile. + * @param int $stackPtr The position of the T_STRING function token. + * + * @return string|false The algorithm name without quotes if this was a relevant hash + * function call or false if it was not. + */ + public function getHashAlgorithmParameter(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + if ($tokens[$stackPtr]['code'] !== \T_STRING) { + return false; + } + + $functionName = $tokens[$stackPtr]['content']; + $functionNameLc = strtolower($functionName); + + // Bow out if not one of the functions we're targetting. + if (isset($this->hashAlgoFunctions[$functionNameLc]) === false) { + return false; + } + + // Get the parameter from the function call which should contain the algorithm name. + $algoParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, $this->hashAlgoFunctions[$functionNameLc]); + if ($algoParam === false) { + return false; + } + + // Algorithm is a text string, so we need to remove the quotes. + $algo = strtolower(trim($algoParam['raw'])); + $algo = $this->stripQuotes($algo); + + return $algo; + } + + + /** + * Determine whether an arbitrary T_STRING token is the use of a global constant. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the T_STRING token. + * + * @return bool + */ + public function isUseOfGlobalConstant(File $phpcsFile, $stackPtr) + { + static $isLowPHPCS, $isLowPHP; + + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // Is this one of the tokens this function handles ? + if ($tokens[$stackPtr]['code'] !== \T_STRING) { + return false; + } + + // Check for older PHP, PHPCS version so we can compensate for misidentified tokens. + if (isset($isLowPHPCS, $isLowPHP) === false) { + $isLowPHP = false; + $isLowPHPCS = false; + if (version_compare(\PHP_VERSION_ID, '50400', '<')) { + $isLowPHP = true; + $isLowPHPCS = version_compare(PHPCSHelper::getVersion(), '2.4.0', '<'); + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === \T_OPEN_PARENTHESIS + || $tokens[$next]['code'] === \T_DOUBLE_COLON) + ) { + // Function call or declaration. + return false; + } + + // Array of tokens which if found preceding the $stackPtr indicate that a T_STRING is not a global constant. + $tokensToIgnore = array( + 'T_NAMESPACE' => true, + 'T_USE' => true, + 'T_CLASS' => true, + 'T_TRAIT' => true, + 'T_INTERFACE' => true, + 'T_EXTENDS' => true, + 'T_IMPLEMENTS' => true, + 'T_NEW' => true, + 'T_FUNCTION' => true, + 'T_DOUBLE_COLON' => true, + 'T_OBJECT_OPERATOR' => true, + 'T_INSTANCEOF' => true, + 'T_INSTEADOF' => true, + 'T_GOTO' => true, + 'T_AS' => true, + 'T_PUBLIC' => true, + 'T_PROTECTED' => true, + 'T_PRIVATE' => true, + ); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev !== false + && (isset($tokensToIgnore[$tokens[$prev]['type']]) === true + || ($tokens[$prev]['code'] === \T_STRING + && (($isLowPHPCS === true + && $tokens[$prev]['content'] === 'trait') + || ($isLowPHP === true + && $tokens[$prev]['content'] === 'insteadof')))) + ) { + // Not the use of a constant. + return false; + } + + if ($prev !== false + && $tokens[$prev]['code'] === \T_NS_SEPARATOR + && $tokens[($prev - 1)]['code'] === \T_STRING + ) { + // Namespaced constant of the same name. + return false; + } + + if ($prev !== false + && $tokens[$prev]['code'] === \T_CONST + && $this->isClassConstant($phpcsFile, $prev) === true + ) { + // Class constant declaration of the same name. + return false; + } + + /* + * Deal with a number of variations of use statements. + */ + for ($i = $stackPtr; $i > 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + break; + } + } + + $firstOnLine = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($firstOnLine !== false && $tokens[$firstOnLine]['code'] === \T_USE) { + $nextOnLine = $phpcsFile->findNext(Tokens::$emptyTokens, ($firstOnLine + 1), null, true); + if ($nextOnLine !== false) { + if (($tokens[$nextOnLine]['code'] === \T_STRING && $tokens[$nextOnLine]['content'] === 'const') + || $tokens[$nextOnLine]['code'] === \T_CONST // Happens in some PHPCS versions. + ) { + $hasNsSep = $phpcsFile->findNext(\T_NS_SEPARATOR, ($nextOnLine + 1), $stackPtr); + if ($hasNsSep !== false) { + // Namespaced const (group) use statement. + return false; + } + } else { + // Not a const use statement. + return false; + } + } + } + + return true; + } + + + /** + * Determine whether the tokens between $start and $end together form a positive number + * as recognized by PHP. + * + * The outcome of this function is reliable for `true`, `false` should be regarded as + * "undetermined". + * + * Note: Zero is *not* regarded as a positive number. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param bool $allowFloats Whether to only consider integers, or also floats. + * + * @return bool True if PHP would evaluate the snippet as a positive number. + * False if not or if it could not be reliably determined + * (variable or calculations and such). + */ + public function isPositiveNumber(File $phpcsFile, $start, $end, $allowFloats = false) + { + $number = $this->isNumber($phpcsFile, $start, $end, $allowFloats); + + if ($number === false) { + return false; + } + + return ($number > 0); + } + + + /** + * Determine whether the tokens between $start and $end together form a negative number + * as recognized by PHP. + * + * The outcome of this function is reliable for `true`, `false` should be regarded as + * "undetermined". + * + * Note: Zero is *not* regarded as a negative number. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param bool $allowFloats Whether to only consider integers, or also floats. + * + * @return bool True if PHP would evaluate the snippet as a negative number. + * False if not or if it could not be reliably determined + * (variable or calculations and such). + */ + public function isNegativeNumber(File $phpcsFile, $start, $end, $allowFloats = false) + { + $number = $this->isNumber($phpcsFile, $start, $end, $allowFloats); + + if ($number === false) { + return false; + } + + return ($number < 0); + } + + /** + * Determine whether the tokens between $start and $end together form a number + * as recognized by PHP. + * + * The outcome of this function is reliable for "true-ish" values, `false` should + * be regarded as "undetermined". + * + * @link https://3v4l.org/npTeM + * + * Mainly intended for examining variable assignments, function call parameters, array values + * where the start and end of the snippet to examine is very clear. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param bool $allowFloats Whether to only consider integers, or also floats. + * + * @return int|float|bool The number found if PHP would evaluate the snippet as a number. + * The return type will be int if $allowFloats is false, if + * $allowFloats is true, the return type will be float. + * False will be returned when the snippet does not evaluate to a + * number or if it could not be reliably determined + * (variable or calculations and such). + */ + protected function isNumber(File $phpcsFile, $start, $end, $allowFloats = false) + { + $stringTokens = Tokens::$heredocTokens + Tokens::$stringTokens; + + $validTokens = array(); + $validTokens[\T_LNUMBER] = true; + $validTokens[\T_TRUE] = true; // Evaluates to int 1. + $validTokens[\T_FALSE] = true; // Evaluates to int 0. + $validTokens[\T_NULL] = true; // Evaluates to int 0. + + if ($allowFloats === true) { + $validTokens[\T_DNUMBER] = true; + } + + $maybeValidTokens = $stringTokens + $validTokens; + + $tokens = $phpcsFile->getTokens(); + $searchEnd = ($end + 1); + $negativeNumber = false; + + if (isset($tokens[$start], $tokens[$searchEnd]) === false) { + return false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $start, $searchEnd, true); + while ($nextNonEmpty !== false + && ($tokens[$nextNonEmpty]['code'] === \T_PLUS + || $tokens[$nextNonEmpty]['code'] === \T_MINUS) + ) { + + if ($tokens[$nextNonEmpty]['code'] === \T_MINUS) { + $negativeNumber = ($negativeNumber === false) ? true : false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), $searchEnd, true); + } + + if ($nextNonEmpty === false || isset($maybeValidTokens[$tokens[$nextNonEmpty]['code']]) === false) { + return false; + } + + $content = false; + if ($tokens[$nextNonEmpty]['code'] === \T_LNUMBER + || $tokens[$nextNonEmpty]['code'] === \T_DNUMBER + ) { + $content = (float) $tokens[$nextNonEmpty]['content']; + } elseif ($tokens[$nextNonEmpty]['code'] === \T_TRUE) { + $content = 1.0; + } elseif ($tokens[$nextNonEmpty]['code'] === \T_FALSE + || $tokens[$nextNonEmpty]['code'] === \T_NULL + ) { + $content = 0.0; + } elseif (isset($stringTokens[$tokens[$nextNonEmpty]['code']]) === true) { + + if ($tokens[$nextNonEmpty]['code'] === \T_START_HEREDOC + || $tokens[$nextNonEmpty]['code'] === \T_START_NOWDOC + ) { + // Skip past heredoc/nowdoc opener to the first content. + $firstDocToken = $phpcsFile->findNext(array(\T_HEREDOC, \T_NOWDOC), ($nextNonEmpty + 1), $searchEnd); + if ($firstDocToken === false) { + // Live coding or parse error. + return false; + } + + $stringContent = $content = $tokens[$firstDocToken]['content']; + + // Skip forward to the end in preparation for the next part of the examination. + $nextNonEmpty = $phpcsFile->findNext(array(\T_END_HEREDOC, \T_END_NOWDOC), ($nextNonEmpty + 1), $searchEnd); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return false; + } + } else { + // Gather subsequent lines for a multi-line string. + for ($i = $nextNonEmpty; $i < $searchEnd; $i++) { + if ($tokens[$i]['code'] !== $tokens[$nextNonEmpty]['code']) { + break; + } + $content .= $tokens[$i]['content']; + } + + $nextNonEmpty = --$i; + $content = $this->stripQuotes($content); + $stringContent = $content; + } + + /* + * Regexes based on the formats outlined in the manual, created by JRF. + * @link https://www.php.net/manual/en/language.types.float.php + */ + $regexInt = '`^\s*[0-9]+`'; + $regexFloat = '`^\s*(?:[+-]?(?:(?:(?P[0-9]+)|(?P([0-9]*\.(?P>LNUM)|(?P>LNUM)\.[0-9]*)))[eE][+-]?(?P>LNUM))|(?P>DNUM))`'; + + $intString = preg_match($regexInt, $content, $intMatch); + $floatString = preg_match($regexFloat, $content, $floatMatch); + + // Does the text string start with a number ? If so, PHP would juggle it and use it as a number. + if ($allowFloats === false) { + if ($intString !== 1 || $floatString === 1) { + if ($floatString === 1) { + // Found float. Only integers targetted. + return false; + } + + $content = 0.0; + } else { + $content = (float) trim($intMatch[0]); + } + } else { + if ($intString !== 1 && $floatString !== 1) { + $content = 0.0; + } else { + $content = ($floatString === 1) ? (float) trim($floatMatch[0]) : (float) trim($intMatch[0]); + } + } + + // Allow for different behaviour for hex numeric strings between PHP 5 vs PHP 7. + if ($intString === 1 && trim($intMatch[0]) === '0' + && preg_match('`^\s*(0x[A-Fa-f0-9]+)`', $stringContent, $hexNumberString) === 1 + && $this->supportsBelow('5.6') === true + ) { + // The filter extension still allows for hex numeric strings in PHP 7, so + // use that to get the numeric value if possible. + // If the filter extension is not available, the value will be zero, but so be it. + if (function_exists('filter_var')) { + $filtered = filter_var($hexNumberString[1], \FILTER_VALIDATE_INT, \FILTER_FLAG_ALLOW_HEX); + if ($filtered !== false) { + $content = $filtered; + } + } + } + } + + // OK, so we have a number, now is there still more code after it ? + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), $searchEnd, true); + if ($nextNonEmpty !== false) { + return false; + } + + if ($negativeNumber === true) { + $content = -$content; + } + + if ($allowFloats === false) { + return (int) $content; + } + + return $content; + } + + + /** + * Determine whether the tokens between $start and $end together form a numberic calculation + * as recognized by PHP. + * + * The outcome of this function is reliable for `true`, `false` should be regarded as "undetermined". + * + * Mainly intended for examining variable assignments, function call parameters, array values + * where the start and end of the snippet to examine is very clear. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Start of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * @param int $end End of the snippet (inclusive), i.e. this + * token will be examined as part of the snippet. + * + * @return bool + */ + protected function isNumericCalculation(File $phpcsFile, $start, $end) + { + $arithmeticTokens = Tokens::$arithmeticTokens; + + // phpcs:disable PHPCompatibility.Constants.NewConstants.t_powFound + if (\defined('T_POW') && isset($arithmeticTokens[\T_POW]) === false) { + // T_POW was not added to the arithmetic array until PHPCS 2.9.0. + $arithmeticTokens[\T_POW] = \T_POW; + } + // phpcs:enable + + $skipTokens = Tokens::$emptyTokens; + $skipTokens[] = \T_MINUS; + $skipTokens[] = \T_PLUS; + + // Find the first arithmetic operator, but skip past +/- signs before numbers. + $nextNonEmpty = ($start - 1); + do { + $nextNonEmpty = $phpcsFile->findNext($skipTokens, ($nextNonEmpty + 1), ($end + 1), true); + $arithmeticOperator = $phpcsFile->findNext($arithmeticTokens, ($nextNonEmpty + 1), ($end + 1)); + } while ($nextNonEmpty !== false && $arithmeticOperator !== false && $nextNonEmpty === $arithmeticOperator); + + if ($arithmeticOperator === false) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + $subsetStart = $start; + $subsetEnd = ($arithmeticOperator - 1); + + while ($this->isNumber($phpcsFile, $subsetStart, $subsetEnd, true) !== false + && isset($tokens[($arithmeticOperator + 1)]) === true + ) { + // Recognize T_POW for PHPCS < 2.4.0 on low PHP versions. + if (\defined('T_POW') === false + && $tokens[$arithmeticOperator]['code'] === \T_MULTIPLY + && $tokens[($arithmeticOperator + 1)]['code'] === \T_MULTIPLY + && isset($tokens[$arithmeticOperator + 2]) === true + ) { + // Move operator one forward to the second * in T_POW. + ++$arithmeticOperator; + } + + $subsetStart = ($arithmeticOperator + 1); + $nextNonEmpty = $arithmeticOperator; + do { + $nextNonEmpty = $phpcsFile->findNext($skipTokens, ($nextNonEmpty + 1), ($end + 1), true); + $arithmeticOperator = $phpcsFile->findNext($arithmeticTokens, ($nextNonEmpty + 1), ($end + 1)); + } while ($nextNonEmpty !== false && $arithmeticOperator !== false && $nextNonEmpty === $arithmeticOperator); + + if ($arithmeticOperator === false) { + // Last calculation operator already reached. + if ($this->isNumber($phpcsFile, $subsetStart, $end, true) !== false) { + return true; + } + + return false; + } + + $subsetEnd = ($arithmeticOperator - 1); + } + + return false; + } + + + + /** + * Determine whether a ternary is a short ternary, i.e. without "middle". + * + * N.B.: This is a back-fill for a new method which is expected to go into + * PHP_CodeSniffer 3.5.0. + * Once that method has been merged into PHPCS, this one should be moved + * to the PHPCSHelper.php file. + * + * @since 9.2.0 + * + * @codeCoverageIgnore Method as pulled upstream is accompanied by unit tests. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the ternary operator + * in the stack. + * + * @return bool True if short ternary, or false otherwise. + */ + public function isShortTernary(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]) === false + || $tokens[$stackPtr]['code'] !== \T_INLINE_THEN + ) { + return false; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return false; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_INLINE_ELSE) { + return true; + } + + return false; + } + + + /** + * Determine whether a T_OPEN/CLOSE_SHORT_ARRAY token is a list() construct. + * + * Note: A variety of PHPCS versions have bugs in the tokenizing of short arrays. + * In that case, the tokens are identified as T_OPEN/CLOSE_SQUARE_BRACKET. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function isShortList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check for the existence of the token. + if (isset($tokens[$stackPtr]) === false) { + return false; + } + + // Is this one of the tokens this function handles ? + if ($tokens[$stackPtr]['code'] !== \T_OPEN_SHORT_ARRAY + && $tokens[$stackPtr]['code'] !== \T_CLOSE_SHORT_ARRAY + ) { + return false; + } + + switch ($tokens[$stackPtr]['code']) { + case \T_OPEN_SHORT_ARRAY: + if (isset($tokens[$stackPtr]['bracket_closer']) === true) { + $opener = $stackPtr; + $closer = $tokens[$stackPtr]['bracket_closer']; + } + break; + + case \T_CLOSE_SHORT_ARRAY: + if (isset($tokens[$stackPtr]['bracket_opener']) === true) { + $opener = $tokens[$stackPtr]['bracket_opener']; + $closer = $stackPtr; + } + break; + } + + if (isset($opener, $closer) === false) { + // Parse error, live coding or real square bracket. + return false; + } + + /* + * PHPCS cross-version compatibility: work around for square brackets misidentified + * as short array when preceded by a variable variable in older PHPCS versions. + */ + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true, null, true); + + if ($prevNonEmpty !== false + && $tokens[$prevNonEmpty]['code'] === \T_CLOSE_CURLY_BRACKET + && isset($tokens[$prevNonEmpty]['bracket_opener']) === true + ) { + $maybeVariableVariable = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokens[$prevNonEmpty]['bracket_opener'] - 1), + null, + true, + null, + true + ); + + if ($tokens[$maybeVariableVariable]['code'] === \T_VARIABLE + || $tokens[$maybeVariableVariable]['code'] === \T_DOLLAR + ) { + return false; + } + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($closer + 1), null, true, null, true); + + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === \T_EQUAL) { + return true; + } + + if ($prevNonEmpty !== false + && $tokens[$prevNonEmpty]['code'] === \T_AS + && isset($tokens[$prevNonEmpty]['nested_parenthesis']) === true + ) { + $parentheses = array_reverse($tokens[$prevNonEmpty]['nested_parenthesis'], true); + foreach ($parentheses as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) + && $tokens[$tokens[$open]['parenthesis_owner']]['code'] === \T_FOREACH + ) { + return true; + } + } + } + + // Maybe this is a short list syntax nested inside another short list syntax ? + $parentOpener = $opener; + do { + $parentOpener = $phpcsFile->findPrevious( + array(\T_OPEN_SHORT_ARRAY, \T_OPEN_SQUARE_BRACKET), + ($parentOpener - 1), + null, + false, + null, + true + ); + + if ($parentOpener === false) { + return false; + } + + } while (isset($tokens[$parentOpener]['bracket_closer']) === true + && $tokens[$parentOpener]['bracket_closer'] < $opener + ); + + if (isset($tokens[$parentOpener]['bracket_closer']) === true + && $tokens[$parentOpener]['bracket_closer'] > $closer + ) { + // Work around tokenizer issue in PHPCS 2.0 - 2.7. + $phpcsVersion = PHPCSHelper::getVersion(); + if ((version_compare($phpcsVersion, '2.0', '>') === true + && version_compare($phpcsVersion, '2.8', '<') === true) + && $tokens[$parentOpener]['code'] === \T_OPEN_SQUARE_BRACKET + ) { + $nextNonEmpty = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($tokens[$parentOpener]['bracket_closer'] + 1), + null, + true, + null, + true + ); + + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === \T_EQUAL) { + return true; + } + + return false; + } + + return $this->isShortList($phpcsFile, $parentOpener); + } + + return false; + } + + + /** + * Determine whether the tokens between $start and $end could together represent a variable. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start Starting point stack pointer. Inclusive. + * I.e. this token should be taken into account. + * @param int $end End point stack pointer. Exclusive. + * I.e. this token should not be taken into account. + * @param int $targetNestingLevel The nesting level the variable should be at. + * + * @return bool + */ + public function isVariable(File $phpcsFile, $start, $end, $targetNestingLevel) + { + static $tokenBlackList, $bracketTokens; + + // Create the token arrays only once. + if (isset($tokenBlackList, $bracketTokens) === false) { + + $tokenBlackList = array( + \T_OPEN_PARENTHESIS => \T_OPEN_PARENTHESIS, + \T_STRING_CONCAT => \T_STRING_CONCAT, + ); + $tokenBlackList += Tokens::$assignmentTokens; + $tokenBlackList += Tokens::$equalityTokens; + $tokenBlackList += Tokens::$comparisonTokens; + $tokenBlackList += Tokens::$operators; + $tokenBlackList += Tokens::$booleanOperators; + $tokenBlackList += Tokens::$castTokens; + + /* + * List of brackets which can be part of a variable variable. + * + * Key is the open bracket token, value the close bracket token. + */ + $bracketTokens = array( + \T_OPEN_CURLY_BRACKET => \T_CLOSE_CURLY_BRACKET, + \T_OPEN_SQUARE_BRACKET => \T_CLOSE_SQUARE_BRACKET, + ); + } + + $tokens = $phpcsFile->getTokens(); + + // If no variable at all was found, then it's definitely a no-no. + $hasVariable = $phpcsFile->findNext(\T_VARIABLE, $start, $end); + if ($hasVariable === false) { + return false; + } + + // Check if the variable found is at the right level. Deeper levels are always an error. + if (isset($tokens[$hasVariable]['nested_parenthesis']) + && \count($tokens[$hasVariable]['nested_parenthesis']) !== $targetNestingLevel + ) { + return false; + } + + // Ok, so the first variable is at the right level, now are there any + // blacklisted tokens within the empty() ? + $hasBadToken = $phpcsFile->findNext($tokenBlackList, $start, $end); + if ($hasBadToken === false) { + return true; + } + + // If there are also bracket tokens, the blacklisted token might be part of a variable + // variable, but if there are no bracket tokens, we know we have an error. + $hasBrackets = $phpcsFile->findNext($bracketTokens, $start, $end); + if ($hasBrackets === false) { + return false; + } + + // Ok, we have both a blacklisted token as well as brackets, so we need to walk + // the tokens of the variable variable. + for ($i = $start; $i < $end; $i++) { + // If this is a bracket token, skip to the end of the bracketed expression. + if (isset($bracketTokens[$tokens[$i]['code']], $tokens[$i]['bracket_closer'])) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + // If it's a blacklisted token, not within brackets, we have an error. + if (isset($tokenBlackList[$tokens[$i]['code']])) { + return false; + } + } + + return true; + } + + /** + * Determine whether a T_MINUS/T_PLUS token is a unary operator. + * + * N.B.: This is a back-fill for a new method which is expected to go into + * PHP_CodeSniffer 3.5.0. + * Once that method has been merged into PHPCS, this one should be moved + * to the PHPCSHelper.php file. + * + * @since 9.2.0 + * + * @codeCoverageIgnore Method as pulled upstream is accompanied by unit tests. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the plus/minus token. + * + * @return bool True if the token passed is a unary operator. + * False otherwise or if the token is not a T_PLUS/T_MINUS token. + */ + public static function isUnaryPlusMinus(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]) === false + || ($tokens[$stackPtr]['code'] !== \T_PLUS + && $tokens[$stackPtr]['code'] !== \T_MINUS) + ) { + return false; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false) { + // Live coding or parse error. + return false; + } + + if (isset(Tokens::$operators[$tokens[$next]['code']]) === true) { + // Next token is an operator, so this is not a unary. + return false; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($tokens[$prev]['code'] === \T_RETURN) { + // Just returning a positive/negative value; eg. (return -1). + return true; + } + + if (isset(Tokens::$operators[$tokens[$prev]['code']]) === true) { + // Just trying to operate on a positive/negative value; eg. ($var * -1). + return true; + } + + if (isset(Tokens::$comparisonTokens[$tokens[$prev]['code']]) === true) { + // Just trying to compare a positive/negative value; eg. ($var === -1). + return true; + } + + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) { + // Just trying to compare a positive/negative value; eg. ($var || -1 === $b). + return true; + } + + if (isset(Tokens::$assignmentTokens[$tokens[$prev]['code']]) === true) { + // Just trying to assign a positive/negative value; eg. ($var = -1). + return true; + } + + if (isset(Tokens::$castTokens[$tokens[$prev]['code']]) === true) { + // Just casting a positive/negative value; eg. (string) -$var. + return true; + } + + // Other indicators that a plus/minus sign is a unary operator. + $invalidTokens = array( + \T_COMMA => true, + \T_OPEN_PARENTHESIS => true, + \T_OPEN_SQUARE_BRACKET => true, + \T_OPEN_SHORT_ARRAY => true, + \T_COLON => true, + \T_INLINE_THEN => true, + \T_INLINE_ELSE => true, + \T_CASE => true, + \T_OPEN_CURLY_BRACKET => true, + \T_STRING_CONCAT => true, + ); + + if (isset($invalidTokens[$tokens[$prev]['code']]) === true) { + // Just trying to use a positive/negative value; eg. myFunction($var, -2). + return true; + } + + return false; + } + + /** + * Get the complete contents of a multi-line text string. + * + * N.B.: This is a back-fill for a new method which is expected to go into + * PHP_CodeSniffer 3.5.0. + * Once that method has been merged into PHPCS, this one should be moved + * to the PHPCSHelper.php file. + * + * @since 9.3.0 + * + * @codeCoverageIgnore Method as pulled upstream is accompanied by unit tests. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr Pointer to the first text string token + * of a multi-line text string or to a + * Nowdoc/Heredoc opener. + * @param bool $stripQuotes Optional. Whether to strip text delimiter + * quotes off the resulting text string. + * Defaults to true. + * + * @return string + * + * @throws \PHP_CodeSniffer_Exception If the specified position is not a + * valid text string token or if the + * token is not the first text string token. + */ + public function getCompleteTextString(File $phpcsFile, $stackPtr, $stripQuotes = true) + { + $tokens = $phpcsFile->getTokens(); + + // Must be the start of a text string token. + if ($tokens[$stackPtr]['code'] !== \T_START_HEREDOC + && $tokens[$stackPtr]['code'] !== \T_START_NOWDOC + && $tokens[$stackPtr]['code'] !== \T_CONSTANT_ENCAPSED_STRING + && $tokens[$stackPtr]['code'] !== \T_DOUBLE_QUOTED_STRING + ) { + throw new PHPCS_Exception('$stackPtr must be of type T_START_HEREDOC, T_START_NOWDOC, T_CONSTANT_ENCAPSED_STRING or T_DOUBLE_QUOTED_STRING'); + } + + if ($tokens[$stackPtr]['code'] === \T_CONSTANT_ENCAPSED_STRING + || $tokens[$stackPtr]['code'] === \T_DOUBLE_QUOTED_STRING + ) { + $prev = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['code'] === $tokens[$prev]['code']) { + throw new PHPCS_Exception('$stackPtr must be the start of the text string'); + } + } + + switch ($tokens[$stackPtr]['code']) { + case \T_START_HEREDOC: + $stripQuotes = false; + $targetType = \T_HEREDOC; + $current = ($stackPtr + 1); + break; + + case \T_START_NOWDOC: + $stripQuotes = false; + $targetType = \T_NOWDOC; + $current = ($stackPtr + 1); + break; + + default: + $targetType = $tokens[$stackPtr]['code']; + $current = $stackPtr; + break; + } + + $string = ''; + do { + $string .= $tokens[$current]['content']; + ++$current; + } while ($tokens[$current]['code'] === $targetType); + + if ($stripQuotes === true) { + return $this->stripQuotes($string); + } + + return $string; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php new file mode 100644 index 000000000..d0d74dfe0 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/ForbiddenAbstractPrivateMethodsSniff.php @@ -0,0 +1,90 @@ + true, + 'T_TRAIT' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.1') === false) { + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) === false) { + // Function, not method. + return; + } + + $properties = $phpcsFile->getMethodProperties($stackPtr); + if ($properties['scope'] !== 'private' || $properties['is_abstract'] !== true) { + return; + } + + $phpcsFile->addError( + 'Abstract methods cannot be declared as private since PHP 5.1', + $stackPtr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php new file mode 100644 index 000000000..572b6fcc0 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewAnonymousClassesSniff.php @@ -0,0 +1,91 @@ + \T_CLASS, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + if (\defined('T_ANON_CLASS')) { + $this->indicators[\T_ANON_CLASS] = \T_ANON_CLASS; + } + + return array(\T_NEW); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if ($nextNonEmpty === false || isset($this->indicators[$tokens[$nextNonEmpty]['code']]) === false) { + return; + } + + // Still here ? In that case, it is an anonymous class. + $phpcsFile->addError( + 'Anonymous classes are not supported in PHP 5.6 or earlier', + $stackPtr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php new file mode 100644 index 000000000..19e5e439e --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewClassesSniff.php @@ -0,0 +1,913 @@ + array(string => bool)) + */ + protected $newClasses = array( + 'ArrayObject' => array( + '4.4' => false, + '5.0' => true, + ), + 'ArrayIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'CachingIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'DirectoryIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'RecursiveDirectoryIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'RecursiveIteratorIterator' => array( + '4.4' => false, + '5.0' => true, + ), + 'php_user_filter' => array( + '4.4' => false, + '5.0' => true, + ), + 'tidy' => array( + '4.4' => false, + '5.0' => true, + ), + + 'SimpleXMLElement' => array( + '5.0.0' => false, + '5.0.1' => true, + ), + 'tidyNode' => array( + '5.0.0' => false, + '5.0.1' => true, + ), + + 'libXMLError' => array( + '5.0' => false, + '5.1' => true, + ), + 'PDO' => array( + '5.0' => false, + '5.1' => true, + ), + 'PDOStatement' => array( + '5.0' => false, + '5.1' => true, + ), + 'AppendIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'EmptyIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'FilterIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'InfiniteIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'IteratorIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'LimitIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'NoRewindIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'ParentIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveArrayIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveCachingIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveFilterIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'SimpleXMLIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'SplFileObject' => array( + '5.0' => false, + '5.1' => true, + ), + 'XMLReader' => array( + '5.0' => false, + '5.1' => true, + ), + + 'SplFileInfo' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'SplTempFileObject' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'XMLWriter' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + + 'DateTime' => array( + '5.1' => false, + '5.2' => true, + ), + 'DateTimeZone' => array( + '5.1' => false, + '5.2' => true, + ), + 'RegexIterator' => array( + '5.1' => false, + '5.2' => true, + ), + 'RecursiveRegexIterator' => array( + '5.1' => false, + '5.2' => true, + ), + 'ReflectionFunctionAbstract' => array( + '5.1' => false, + '5.2' => true, + ), + 'ZipArchive' => array( + '5.1' => false, + '5.2' => true, + ), + + 'Closure' => array( + '5.2' => false, + '5.3' => true, + ), + 'DateInterval' => array( + '5.2' => false, + '5.3' => true, + ), + 'DatePeriod' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo' => array( + '5.2' => false, + '5.3' => true, + ), + 'Collator' => array( + '5.2' => false, + '5.3' => true, + ), + 'NumberFormatter' => array( + '5.2' => false, + '5.3' => true, + ), + 'Locale' => array( + '5.2' => false, + '5.3' => true, + ), + 'Normalizer' => array( + '5.2' => false, + '5.3' => true, + ), + 'MessageFormatter' => array( + '5.2' => false, + '5.3' => true, + ), + 'IntlDateFormatter' => array( + '5.2' => false, + '5.3' => true, + ), + 'Phar' => array( + '5.2' => false, + '5.3' => true, + ), + 'PharData' => array( + '5.2' => false, + '5.3' => true, + ), + 'PharFileInfo' => array( + '5.2' => false, + '5.3' => true, + ), + 'FilesystemIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'GlobIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'MultipleIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'RecursiveTreeIterator' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplDoublyLinkedList' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplFixedArray' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplHeap' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplMaxHeap' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplMinHeap' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplObjectStorage' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplPriorityQueue' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplQueue' => array( + '5.2' => false, + '5.3' => true, + ), + 'SplStack' => array( + '5.2' => false, + '5.3' => true, + ), + + 'ResourceBundle' => array( + '5.3.1' => false, + '5.3.2' => true, + ), + + 'CallbackFilterIterator' => array( + '5.3' => false, + '5.4' => true, + ), + 'RecursiveCallbackFilterIterator' => array( + '5.3' => false, + '5.4' => true, + ), + 'ReflectionZendExtension' => array( + '5.3' => false, + '5.4' => true, + ), + 'SessionHandler' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP' => array( + '5.3' => false, + '5.4' => true, + ), + 'Transliterator' => array( + '5.3' => false, + '5.4' => true, + ), + 'Spoofchecker' => array( + '5.3' => false, + '5.4' => true, + ), + + 'Generator' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLFile' => array( + '5.4' => false, + '5.5' => true, + ), + 'DateTimeImmutable' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlCalendar' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlGregorianCalendar' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlTimeZone' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlBreakIterator' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlRuleBasedBreakIterator' => array( + '5.4' => false, + '5.5' => true, + ), + 'IntlCodePointBreakIterator' => array( + '5.4' => false, + '5.5' => true, + ), + 'UConverter' => array( + '5.4' => false, + '5.5' => true, + ), + + 'GMP' => array( + '5.5' => false, + '5.6' => true, + ), + + 'IntlChar' => array( + '5.6' => false, + '7.0' => true, + ), + 'ReflectionType' => array( + '5.6' => false, + '7.0' => true, + ), + 'ReflectionGenerator' => array( + '5.6' => false, + '7.0' => true, + ), + + 'ReflectionClassConstant' => array( + '7.0' => false, + '7.1' => true, + ), + + 'FFI' => array( + '7.3' => false, + '7.4' => true, + ), + 'FFI\CData' => array( + '7.3' => false, + '7.4' => true, + ), + 'FFI\CType' => array( + '7.3' => false, + '7.4' => true, + ), + 'ReflectionReference' => array( + '7.3' => false, + '7.4' => true, + ), + 'WeakReference' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + /** + * A list of new Exception classes, not present in older versions. + * + * The array lists : version number with false (not present) or true (present). + * If's sufficient to list the first version where the class appears. + * + * {@internal Classes listed here do not need to be added to the $newClasses + * property as well. + * This list is automatically added to the $newClasses property + * in the `register()` method.} + * + * {@internal Helper to update this list: https://3v4l.org/MhlUp} + * + * @since 7.1.4 + * + * @var array(string => array(string => bool)) + */ + protected $newExceptions = array( + 'com_exception' => array( + '4.4' => false, + '5.0' => true, + ), + 'DOMException' => array( + '4.4' => false, + '5.0' => true, + ), + 'Exception' => array( + // According to the docs introduced in PHP 5.1, but this appears to be. + // an error. Class was introduced with try/catch keywords in PHP 5.0. + '4.4' => false, + '5.0' => true, + ), + 'ReflectionException' => array( + '4.4' => false, + '5.0' => true, + ), + 'SoapFault' => array( + '4.4' => false, + '5.0' => true, + ), + 'SQLiteException' => array( + '4.4' => false, + '5.0' => true, + ), + + 'ErrorException' => array( + '5.0' => false, + '5.1' => true, + ), + 'BadFunctionCallException' => array( + '5.0' => false, + '5.1' => true, + ), + 'BadMethodCallException' => array( + '5.0' => false, + '5.1' => true, + ), + 'DomainException' => array( + '5.0' => false, + '5.1' => true, + ), + 'InvalidArgumentException' => array( + '5.0' => false, + '5.1' => true, + ), + 'LengthException' => array( + '5.0' => false, + '5.1' => true, + ), + 'LogicException' => array( + '5.0' => false, + '5.1' => true, + ), + 'mysqli_sql_exception' => array( + '5.0' => false, + '5.1' => true, + ), + 'OutOfBoundsException' => array( + '5.0' => false, + '5.1' => true, + ), + 'OutOfRangeException' => array( + '5.0' => false, + '5.1' => true, + ), + 'OverflowException' => array( + '5.0' => false, + '5.1' => true, + ), + 'PDOException' => array( + '5.0' => false, + '5.1' => true, + ), + 'RangeException' => array( + '5.0' => false, + '5.1' => true, + ), + 'RuntimeException' => array( + '5.0' => false, + '5.1' => true, + ), + 'UnderflowException' => array( + '5.0' => false, + '5.1' => true, + ), + 'UnexpectedValueException' => array( + '5.0' => false, + '5.1' => true, + ), + + 'PharException' => array( + '5.2' => false, + '5.3' => true, + ), + + 'SNMPException' => array( + '5.3' => false, + '5.4' => true, + ), + + 'IntlException' => array( + '5.4' => false, + '5.5' => true, + ), + + 'Error' => array( + '5.6' => false, + '7.0' => true, + ), + 'ArithmeticError' => array( + '5.6' => false, + '7.0' => true, + ), + 'AssertionError' => array( + '5.6' => false, + '7.0' => true, + ), + 'DivisionByZeroError' => array( + '5.6' => false, + '7.0' => true, + ), + 'ParseError' => array( + '5.6' => false, + '7.0' => true, + ), + 'TypeError' => array( + '5.6' => false, + '7.0' => true, + ), + 'ClosedGeneratorException' => array( + '5.6' => false, + '7.0' => true, + ), + 'UI\Exception\InvalidArgumentException' => array( + '5.6' => false, + '7.0' => true, + ), + 'UI\Exception\RuntimeException' => array( + '5.6' => false, + '7.0' => true, + ), + + 'ArgumentCountError' => array( + '7.0' => false, + '7.1' => true, + ), + + 'SodiumException' => array( + '7.1' => false, + '7.2' => true, + ), + + 'CompileError' => array( + '7.2' => false, + '7.3' => true, + ), + 'JsonException' => array( + '7.2' => false, + '7.3' => true, + ), + + 'FFI\Exception' => array( + '7.3' => false, + '7.4' => true, + ), + 'FFI\ParserException' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * @since 7.0.3 - Now also targets the `class` keyword to detect extended classes. + * - Now also targets double colons to detect static class use. + * @since 7.1.4 - Now also targets anonymous classes to detect extended classes. + * - Now also targets functions/closures to detect new classes used + * as parameter type declarations. + * - Now also targets the `catch` control structure to detect new + * exception classes being caught. + * @since 8.2.0 Now also targets the `T_RETURN_TYPE` token to detect new classes used + * as return type declarations. + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of class names. + $this->newClasses = $this->arrayKeysToLowercase($this->newClasses); + $this->newExceptions = $this->arrayKeysToLowercase($this->newExceptions); + + // Add the Exception classes to the Classes list. + $this->newClasses = array_merge($this->newClasses, $this->newExceptions); + + $targets = array( + \T_NEW, + \T_CLASS, + \T_DOUBLE_COLON, + \T_FUNCTION, + \T_CLOSURE, + \T_CATCH, + ); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + if (\defined('T_RETURN_TYPE')) { + $targets[] = \T_RETURN_TYPE; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + case 'T_FUNCTION': + case 'T_CLOSURE': + $this->processFunctionToken($phpcsFile, $stackPtr); + + // Deal with older PHPCS version which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $this->processReturnTypeToken($phpcsFile, $returnTypeHint); + } + break; + + case 'T_CATCH': + $this->processCatchToken($phpcsFile, $stackPtr); + break; + + case 'T_RETURN_TYPE': + $this->processReturnTypeToken($phpcsFile, $stackPtr); + break; + + default: + $this->processSingularToken($phpcsFile, $stackPtr); + break; + } + } + + + /** + * Processes this test for when a token resulting in a singular class name is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processSingularToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $FQClassName = ''; + + if ($tokens[$stackPtr]['type'] === 'T_NEW') { + $FQClassName = $this->getFQClassNameFromNewToken($phpcsFile, $stackPtr); + + } elseif ($tokens[$stackPtr]['type'] === 'T_CLASS' || $tokens[$stackPtr]['type'] === 'T_ANON_CLASS') { + $FQClassName = $this->getFQExtendedClassName($phpcsFile, $stackPtr); + + } elseif ($tokens[$stackPtr]['type'] === 'T_DOUBLE_COLON') { + $FQClassName = $this->getFQClassNameFromDoubleColonToken($phpcsFile, $stackPtr); + } + + if ($FQClassName === '') { + return; + } + + $className = substr($FQClassName, 1); // Remove global namespace indicator. + $classNameLc = strtolower($className); + + if (isset($this->newClasses[$classNameLc]) === false) { + return; + } + + $itemInfo = array( + 'name' => $className, + 'nameLc' => $classNameLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Processes this test for when a function token is encountered. + * + * - Detect new classes when used as a parameter type declaration. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processFunctionToken(File $phpcsFile, $stackPtr) + { + // Retrieve typehints stripped of global NS indicator and/or nullable indicator. + $typeHints = $this->getTypeHintsFromFunctionDeclaration($phpcsFile, $stackPtr); + if (empty($typeHints) || \is_array($typeHints) === false) { + return; + } + + foreach ($typeHints as $hint) { + + $typeHintLc = strtolower($hint); + + if (isset($this->newClasses[$typeHintLc]) === true) { + $itemInfo = array( + 'name' => $hint, + 'nameLc' => $typeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + } + + + /** + * Processes this test for when a catch token is encountered. + * + * - Detect exceptions when used in a catch statement. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processCatchToken(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Bow out during live coding. + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = ($tokens[$stackPtr]['parenthesis_closer'] + 1); + $name = ''; + $listen = array( + // Parts of a (namespaced) class name. + \T_STRING => true, + \T_NS_SEPARATOR => true, + // End/split tokens. + \T_VARIABLE => false, + \T_BITWISE_OR => false, + \T_CLOSE_CURLY_BRACKET => false, // Shouldn't be needed as we expect a var before this. + ); + + for ($i = ($opener + 1); $i < $closer; $i++) { + if (isset($listen[$tokens[$i]['code']]) === false) { + continue; + } + + if ($listen[$tokens[$i]['code']] === true) { + $name .= $tokens[$i]['content']; + continue; + } else { + if (empty($name) === true) { + // Weird, we should have a name by the time we encounter a variable or |. + // So this may be the closer. + continue; + } + + $name = ltrim($name, '\\'); + $nameLC = strtolower($name); + + if (isset($this->newExceptions[$nameLC]) === true) { + $itemInfo = array( + 'name' => $name, + 'nameLc' => $nameLC, + ); + $this->handleFeature($phpcsFile, $i, $itemInfo); + } + + // Reset for a potential multi-catch. + $name = ''; + } + } + } + + + /** + * Processes this test for when a return type token is encountered. + * + * - Detect new classes when used as a return type declaration. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processReturnTypeToken(File $phpcsFile, $stackPtr) + { + $returnTypeHint = $this->getReturnTypeHintName($phpcsFile, $stackPtr); + if (empty($returnTypeHint)) { + return; + } + + $returnTypeHint = ltrim($returnTypeHint, '\\'); + $returnTypeHintLc = strtolower($returnTypeHint); + + if (isset($this->newClasses[$returnTypeHintLc]) === false) { + return; + } + + // Still here ? Then this is a return type declaration using a new class. + $itemInfo = array( + 'name' => $returnTypeHint, + 'nameLc' => $returnTypeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newClasses[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The built-in class ' . parent::getErrorMsgTemplate(); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php new file mode 100644 index 000000000..d2cb3feb7 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewConstVisibilitySniff.php @@ -0,0 +1,80 @@ +supportsBelow('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + + // Is the previous token a visibility indicator ? + if ($prevToken === false || isset(Tokens::$scopeModifiers[$tokens[$prevToken]['code']]) === false) { + return; + } + + // Is this a class constant ? + if ($this->isClassConstant($phpcsFile, $stackPtr) === false) { + // This may be a constant declaration in the global namespace with visibility, + // but that would throw a parse error, i.e. not our concern. + return; + } + + $phpcsFile->addError( + 'Visibility indicators for class constants are not supported in PHP 7.0 or earlier. Found "%s const"', + $stackPtr, + 'Found', + array($tokens[$prevToken]['content']) + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php new file mode 100644 index 000000000..9658a76fa --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewLateStaticBindingSniff.php @@ -0,0 +1,88 @@ +findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + if ($nextNonEmpty === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + if ($tokens[$nextNonEmpty]['code'] !== \T_DOUBLE_COLON) { + return; + } + + $inClass = $this->inClassScope($phpcsFile, $stackPtr, false); + + if ($inClass === true && $this->supportsBelow('5.2') === true) { + $phpcsFile->addError( + 'Late static binding is not supported in PHP 5.2 or earlier.', + $stackPtr, + 'Found' + ); + } + + if ($inClass === false) { + $phpcsFile->addError( + 'Late static binding is not supported outside of class scope.', + $stackPtr, + 'OutsideClassScope' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php new file mode 100644 index 000000000..a609acc13 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/NewTypedPropertiesSniff.php @@ -0,0 +1,132 @@ + \T_PRIVATE, + \T_PROTECTED => \T_PROTECTED, + \T_PUBLIC => \T_PUBLIC, + \T_STATIC => \T_STATIC, + \T_VAR => \T_VAR, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_VARIABLE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->isClassProperty($phpcsFile, $stackPtr) === false) { + return; + } + + $find = $this->modifierKeywords; + $find += array( + \T_SEMICOLON => \T_SEMICOLON, + \T_OPEN_CURLY_BRACKET => \T_OPEN_CURLY_BRACKET, + ); + + $tokens = $phpcsFile->getTokens(); + $modifier = $phpcsFile->findPrevious($find, ($stackPtr - 1)); + if ($modifier === false + || $tokens[$modifier]['code'] === \T_SEMICOLON + || $tokens[$modifier]['code'] === \T_OPEN_CURLY_BRACKET + ) { + // Parse error. Ignore. + return; + } + + $type = $phpcsFile->findNext(Tokens::$emptyTokens, ($modifier + 1), null, true); + if ($tokens[$type]['code'] === \T_VARIABLE) { + return; + } + + // Still here ? In that case, this will be a typed property. + if ($this->supportsBelow('7.3') === true) { + $phpcsFile->addError( + 'Typed properties are not supported in PHP 7.3 or earlier', + $type, + 'Found' + ); + } + + if ($this->supportsAbove('7.4') === true) { + // Examine the type to verify it's valid. + if ($tokens[$type]['type'] === 'T_NULLABLE' + // Needed to support PHPCS < 3.5.0 which doesn't correct to the nullable token type yet. + || $tokens[$type]['code'] === \T_INLINE_THEN + ) { + $type = $phpcsFile->findNext(Tokens::$emptyTokens, ($type + 1), null, true); + } + + $content = $tokens[$type]['content']; + if ($content === 'void' || $content === 'callable') { + $phpcsFile->addError( + '%s is not supported as a type declaration for properties', + $type, + 'InvalidType', + array($content) + ); + } + } + + $endOfStatement = $phpcsFile->findNext(\T_SEMICOLON, ($stackPtr + 1)); + if ($endOfStatement !== false) { + // Don't throw the same error multiple times for multi-property declarations. + return ($endOfStatement + 1); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php new file mode 100644 index 000000000..7ecfd6ca0 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Classes/RemovedOrphanedParentSniff.php @@ -0,0 +1,115 @@ + true, + 'T_ANON_CLASS' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_PARENT); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + // Use within the global namespace. Not our concern. + return; + } + + /* + * Find the class within which this parent keyword is used. + */ + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_reverse($conditions, true); + $classPtr = false; + + foreach ($conditions as $ptr => $type) { + if (isset($this->classScopeTokens[$tokens[$ptr]['type']])) { + $classPtr = $ptr; + break; + } + } + + if ($classPtr === false) { + // Use outside of a class scope. Not our concern. + return; + } + + if (isset($tokens[$classPtr]['scope_opener']) === false) { + // No scope opener known. Probably a parse error. + return; + } + + $extends = $phpcsFile->findNext(\T_EXTENDS, ($classPtr + 1), $tokens[$classPtr]['scope_opener']); + if ($extends !== false) { + // Class has a parent. + return; + } + + $phpcsFile->addError( + 'Using "parent" inside a class without parent is deprecated since PHP 7.4', + $stackPtr, + 'Deprecated' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php new file mode 100644 index 000000000..27ec42170 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewConstantsSniff.php @@ -0,0 +1,3756 @@ + array(string => bool)) + */ + protected $newConstants = array( + 'E_STRICT' => array( + '4.4' => false, + '5.0' => true, + ), + // Curl: + 'CURLOPT_FTP_USE_EPRT' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_NOSIGNAL' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_UNRESTRICTED_AUTH' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_BUFFERSIZE' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_HTTPAUTH' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_PROXYPORT' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_PROXYTYPE' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_SSLCERTTYPE' => array( + '4.4' => false, + '5.0' => true, + ), + 'CURLOPT_HTTP200ALIASES' => array( + '4.4' => false, + '5.0' => true, + ), + // OpenSSL: + 'OPENSSL_ALGO_MD2' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_MD4' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_MD5' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_SHA1' => array( + '4.4' => false, + '5.0' => true, + ), + 'OPENSSL_ALGO_DSS1' => array( + '4.4' => false, + '5.0' => true, + ), + // Tokenizer: + 'T_ABSTRACT' => array( + '4.4' => false, + '5.0' => true, + ), + 'T_CATCH' => array( + '4.4' => false, + '5.0' => true, + ), + + 'SORT_LOCALE_STRING' => array( + '5.0.1' => false, + '5.0.2' => true, + ), + 'PHP_EOL' => array( + '5.0.1' => false, + '5.0.2' => true, + ), + + 'PHP_INT_MAX' => array( + '5.0.4' => false, + '5.0.5' => true, + ), + 'PHP_INT_SIZE' => array( + '5.0.4' => false, + '5.0.5' => true, + ), + + '__COMPILER_HALT_OFFSET__' => array( + '5.0' => false, + '5.1' => true, + ), + 'GLOB_ERR' => array( + '5.0' => false, + '5.1' => true, + ), + // Curl: + 'CURLOPT_AUTOREFERER' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_BINARYTRANSFER' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_COOKIESESSION' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_FTPSSLAUTH' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_PROXYAUTH' => array( + '5.0' => false, + '5.1' => true, + ), + 'CURLOPT_TIMECONDITION' => array( + '5.0' => false, + '5.1' => true, + ), + // POSIX: + 'POSIX_F_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_R_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_W_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_X_OK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFBLK' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFCHR' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFIFO' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFREG' => array( + '5.0' => false, + '5.1' => true, + ), + 'POSIX_S_IFSOCK' => array( + '5.0' => false, + '5.1' => true, + ), + // Streams: + 'STREAM_IPPROTO_ICMP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_IP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_RAW' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_TCP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_IPPROTO_UDP' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_PF_INET' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_PF_INET6' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_PF_UNIX' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_DGRAM' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_RAW' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_RDM' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_SEQPACKET' => array( + '5.0' => false, + '5.1' => true, + ), + 'STREAM_SOCK_STREAM' => array( + '5.0' => false, + '5.1' => true, + ), + // Tokenizer: + 'T_HALT_COMPILER' => array( + '5.0' => false, + '5.1' => true, + ), + + // Date/Time: + 'DATE_ATOM' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_COOKIE' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_ISO8601' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC822' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC850' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC1036' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC1123' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC2822' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RFC3339' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_RSS' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + 'DATE_W3C' => array( + '5.1.0' => false, + '5.1.1' => true, + ), + + // Date/Time: + 'SUNFUNCS_RET_TIMESTAMP' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'SUNFUNCS_RET_STRING' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'SUNFUNCS_RET_DOUBLE' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + // XSL: + 'LIBXSLT_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'LIBXSLT_DOTTED_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'LIBEXSLT_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'LIBEXSLT_DOTTED_VERSION' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + // URL: + 'PHP_URL_SCHEME' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_HOST' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_PORT' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_USER' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_PASS' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_PATH' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_QUERY' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_URL_FRAGMENT' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_QUERY_RFC1738' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'PHP_QUERY_RFC3986' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + + // Curl: + 'CURLINFO_HEADER_OUT' => array( + '5.1.2' => false, + '5.1.3' => true, + ), + + // Core: + 'E_RECOVERABLE_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + // Math: + 'M_EULER' => array( + '5.1' => false, + '5.2' => true, + ), + 'M_LNPI' => array( + '5.1' => false, + '5.2' => true, + ), + 'M_SQRT3' => array( + '5.1' => false, + '5.2' => true, + ), + 'M_SQRTPI' => array( + '5.1' => false, + '5.2' => true, + ), + 'PATHINFO_FILENAME' => array( + '5.1' => false, + '5.2' => true, + ), + 'UPLOAD_ERR_EXTENSION' => array( + '5.1' => false, + '5.2' => true, + ), + // Curl: + 'CURLE_FILESIZE_EXCEEDED' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLE_FTP_SSL_FAILED' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLE_LDAP_INVALID_URL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPAUTH_DEFAULT' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPAUTH_SSL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPAUTH_TLS' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_ALL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_CONTROL' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_NONE' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLFTPSSL_TRY' => array( + '5.1' => false, + '5.2' => true, + ), + 'CURLOPT_FTP_SSL' => array( + '5.1' => false, + '5.2' => true, + ), + // Ming: + 'SWFTEXTFIELD_USEFONT' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWFTEXTFIELD_AUTOSIZE' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_NOT_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_ADPCM_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_MP3_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_NOT_COMPRESSED_LE' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_NELLY_COMPRESSED' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_5KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_11KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_22KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_44KHZ' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_8BITS' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_16BITS' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_MONO' => array( + '5.1' => false, + '5.2' => true, + ), + 'SWF_SOUND_STEREO' => array( + '5.1' => false, + '5.2' => true, + ), + // OpenSSL: + 'OPENSSL_KEYTYPE_EC' => array( + '5.1' => false, + '5.2' => true, + ), + 'OPENSSL_VERSION_NUMBER' => array( + '5.1' => false, + '5.2' => true, + ), + 'OPENSSL_VERSION_TEXT' => array( + '5.1' => false, + '5.2' => true, + ), + // PCRE: + 'PREG_BACKTRACK_LIMIT_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_BAD_UTF8_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_INTERNAL_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_NO_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + 'PREG_RECURSION_LIMIT_ERROR' => array( + '5.1' => false, + '5.2' => true, + ), + // Snmp: + 'SNMP_OID_OUTPUT_FULL' => array( + '5.1' => false, + '5.2' => true, + ), + 'SNMP_OID_OUTPUT_NUMERIC' => array( + '5.1' => false, + '5.2' => true, + ), + // Semaphore: + 'MSG_EAGAIN' => array( + '5.1' => false, + '5.2' => true, + ), + 'MSG_ENOMSG' => array( + '5.1' => false, + '5.2' => true, + ), + + // Curl: + 'CURLOPT_TCP_NODELAY' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + + // Stream: + 'STREAM_SHUT_RD' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + 'STREAM_SHUT_WR' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + 'STREAM_SHUT_RDWR' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + + 'GMP_VERSION' => array( + '5.2.1' => false, + '5.2.2' => true, + ), + + // Curl: + 'CURLOPT_TIMEOUT_MS' => array( + '5.2.2' => false, + '5.2.3' => true, + ), + 'CURLOPT_CONNECTTIMEOUT_MS' => array( + '5.2.2' => false, + '5.2.3' => true, + ), + + // Curl: + 'CURLOPT_PRIVATE' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'CURLINFO_PRIVATE' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + // GD: + 'GD_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_MAJOR_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_MINOR_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_RELEASE_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + 'GD_EXTRA_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + // PCRE: + 'PCRE_VERSION' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + + 'PHP_MAJOR_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_MINOR_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_RELEASE_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_VERSION_ID' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_EXTRA_VERSION' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_ZTS' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'PHP_DEBUG' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'FILE_BINARY' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + 'FILE_TEXT' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + // Sockets: + 'TCP_NODELAY' => array( + '5.2.6' => false, + '5.2.7' => true, + ), + + // Curl: + 'CURLOPT_PROTOCOLS' => array( + '5.2.9' => false, + '5.2.10' => true, + ), + 'CURLOPT_REDIR_PROTOCOLS' => array( + '5.2.9' => false, + '5.2.10' => true, + ), + 'CURLPROXY_SOCKS4' => array( + '5.2.9' => false, + '5.2.10' => true, + ), + + // Libxml: + 'LIBXML_PARSEHUGE' => array( + '5.2.11' => false, + '5.2.12' => true, + ), + + // Core: + 'ENT_IGNORE' => array( + '5.2' => false, + '5.3' => true, + ), + 'E_DEPRECATED' => array( + '5.2' => false, + '5.3' => true, + ), + 'E_USER_DEPRECATED' => array( + '5.2' => false, + '5.3' => true, + ), + 'INI_SCANNER_NORMAL' => array( + '5.2' => false, + '5.3' => true, + ), + 'INI_SCANNER_RAW' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_MAXPATHLEN' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_NT_DOMAIN_CONTROLLER' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_NT_SERVER' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_NT_WORKSTATION' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_BUILD' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_MAJOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_MINOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_PLATFORM' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_PRODUCTTYPE' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_SP_MAJOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_SP_MINOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_WINDOWS_VERSION_SUITEMASK' => array( + '5.2' => false, + '5.3' => true, + ), + // Curl: + 'CURLINFO_CERTINFO' => array( + '5.2' => false, + '5.3' => true, + ), + 'CURLOPT_PROGRESSFUNCTION' => array( + '5.2' => false, + '5.3' => true, + ), + 'CURLE_SSH' => array( + '5.2' => false, + '5.3' => true, + ), + // GD: + 'IMG_FILTER_PIXELATE' => array( + '5.2' => false, + '5.3' => true, + ), + 'IMAGETYPE_ICO' => array( + '5.2' => false, + '5.3' => true, + ), + // Fileinfo: + 'FILEINFO_MIME_TYPE' => array( + '5.2' => false, + '5.3' => true, + ), + 'FILEINFO_MIME_ENCODING' => array( + '5.2' => false, + '5.3' => true, + ), + // JSON: + 'JSON_ERROR_CTRL_CHAR' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_DEPTH' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_NONE' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_STATE_MISMATCH' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_ERROR_SYNTAX' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_FORCE_OBJECT' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_TAG' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_AMP' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_APOS' => array( + '5.2' => false, + '5.3' => true, + ), + 'JSON_HEX_QUOT' => array( + '5.2' => false, + '5.3' => true, + ), + // LDAP: + 'LDAP_OPT_NETWORK_TIMEOUT' => array( + '5.2' => false, + '5.3' => true, + ), + // Libxml: + 'LIBXML_LOADED_VERSION' => array( + '5.2' => false, + '5.3' => true, + ), + // Math: + 'PHP_ROUND_HALF_UP' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_ROUND_HALF_DOWN' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_ROUND_HALF_EVEN' => array( + '5.2' => false, + '5.3' => true, + ), + 'PHP_ROUND_HALF_ODD' => array( + '5.2' => false, + '5.3' => true, + ), + // Mysqli + 'MYSQLI_OPT_INT_AND_FLOAT_NATIVE' => array( + '5.2' => false, + '5.3' => true, + ), + 'MYSQLI_OPT_NET_CMD_BUFFER_SIZE' => array( + '5.2' => false, + '5.3' => true, + ), + 'MYSQLI_OPT_NET_READ_BUFFER_SIZE' => array( + '5.2' => false, + '5.3' => true, + ), + 'MYSQLI_OPT_SSL_VERIFY_SERVER_CERT' => array( + '5.2' => false, + '5.3' => true, + ), + // OCI8: + 'OCI_CRED_EXT' => array( + '5.2' => false, + '5.3' => true, + ), + // PCRE: + 'PREG_BAD_UTF8_OFFSET_ERROR' => array( + '5.2' => false, + '5.3' => true, + ), + // PCNTL: + 'BUS_ADRALN' => array( + '5.2' => false, + '5.3' => true, + ), + 'BUS_ADRERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'BUS_OBJERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_CONTIUNED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_DUMPED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_EXITED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_KILLED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_STOPPED' => array( + '5.2' => false, + '5.3' => true, + ), + 'CLD_TRAPPED' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTDIV' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTINV' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTOVF' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTRES' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTSUB' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_FLTUND' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_INTDIV' => array( + '5.2' => false, + '5.3' => true, + ), + 'FPE_INTOVF' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_BADSTK' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_COPROC' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLADR' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLOPC' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLOPN' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_ILLTRP' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_PRVOPC' => array( + '5.2' => false, + '5.3' => true, + ), + 'ILL_PRVREG' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_ERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_HUP' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_IN' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_MSG' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_OUT' => array( + '5.2' => false, + '5.3' => true, + ), + 'POLL_PRI' => array( + '5.2' => false, + '5.3' => true, + ), + 'SEGV_ACCERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'SEGV_MAPERR' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_ASYNCIO' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_KERNEL' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_MSGGQ' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_NOINFO' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_QUEUE' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_SIGIO' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_TIMER' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_TKILL' => array( + '5.2' => false, + '5.3' => true, + ), + 'SI_USER' => array( + '5.2' => false, + '5.3' => true, + ), + 'SIG_BLOCK' => array( + '5.2' => false, + '5.3' => true, + ), + 'SIG_SETMASK' => array( + '5.2' => false, + '5.3' => true, + ), + 'SIG_UNBLOCK' => array( + '5.2' => false, + '5.3' => true, + ), + 'TRAP_BRKPT' => array( + '5.2' => false, + '5.3' => true, + ), + 'TRAP_TRACE' => array( + '5.2' => false, + '5.3' => true, + ), + // Tokenizer: + 'T_DIR' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_GOTO' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_NAMESPACE' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_NS_C' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_NS_SEPARATOR' => array( + '5.2' => false, + '5.3' => true, + ), + 'T_USE' => array( + '5.2' => false, + '5.3' => true, + ), + + // OCI8: + 'OCI_NO_AUTO_COMMIT' => array( + '5.3.1' => false, + '5.3.2' => true, + ), + // OpenSSL: + 'OPENSSL_TLSEXT_SERVER_NAME' => array( + '5.3.1' => false, + '5.3.2' => true, + ), + + // JSON: + 'JSON_ERROR_UTF8' => array( + '5.3.2' => false, + '5.3.3' => true, + ), + 'JSON_NUMERIC_CHECK' => array( + '5.3.2' => false, + '5.3.3' => true, + ), + + 'DEBUG_BACKTRACE_IGNORE_ARGS' => array( + '5.3.5' => false, + '5.3.6' => true, + ), + + 'CURLINFO_REDIRECT_URL' => array( + '5.3.6' => false, + '5.3.7' => true, + ), + 'PHP_MANDIR' => array( + '5.3.6' => false, + '5.3.7' => true, + ), + + 'PHP_BINARY' => array( + '5.3' => false, + '5.4' => true, + ), + 'SORT_NATURAL' => array( + '5.3' => false, + '5.4' => true, + ), + 'SORT_FLAG_CASE' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_HTML401' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_XML1' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_XHTML' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_HTML5' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_SUBSTITUTE' => array( + '5.3' => false, + '5.4' => true, + ), + 'ENT_DISALLOWED' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPPROTO_IP' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPPROTO_IPV6' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPV6_MULTICAST_HOPS' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPV6_MULTICAST_IF' => array( + '5.3' => false, + '5.4' => true, + ), + 'IPV6_MULTICAST_LOOP' => array( + '5.3' => false, + '5.4' => true, + ), + 'IP_MULTICAST_IF' => array( + '5.3' => false, + '5.4' => true, + ), + 'IP_MULTICAST_LOOP' => array( + '5.3' => false, + '5.4' => true, + ), + 'IP_MULTICAST_TTL' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_JOIN_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_LEAVE_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_BLOCK_SOURCE' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_UNBLOCK_SOURCE' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_JOIN_SOURCE_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'MCAST_LEAVE_SOURCE_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + // Curl: + 'CURLOPT_MAX_RECV_SPEED_LARGE' => array( + '5.3' => false, + '5.4' => true, + ), + 'CURLOPT_MAX_SEND_SPEED_LARGE' => array( + '5.3' => false, + '5.4' => true, + ), + // Directories: + 'SCANDIR_SORT_ASCENDING' => array( + '5.3' => false, + '5.4' => true, + ), + 'SCANDIR_SORT_DESCENDING' => array( + '5.3' => false, + '5.4' => true, + ), + 'SCANDIR_SORT_NONE' => array( + '5.3' => false, + '5.4' => true, + ), + // LibXML: + 'LIBXML_HTML_NODEFDTD' => array( + '5.3' => false, + '5.4' => true, + ), + 'LIBXML_HTML_NOIMPLIED' => array( + '5.3' => false, + '5.4' => true, + ), + 'LIBXML_PEDANTIC' => array( + '5.3' => false, + '5.4' => true, + ), + // OpenSSL: + 'OPENSSL_CIPHER_AES_128_CBC' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_CIPHER_AES_192_CBC' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_CIPHER_AES_256_CBC' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_RAW_DATA' => array( + '5.3' => false, + '5.4' => true, + ), + 'OPENSSL_ZERO_PADDING' => array( + '5.3' => false, + '5.4' => true, + ), + // Output buffering: + 'PHP_OUTPUT_HANDLER_CLEAN' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_CLEANABLE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_DISABLED' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_FINAL' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_FLUSH' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_FLUSHABLE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_REMOVABLE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_STARTED' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_STDFLAGS' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_OUTPUT_HANDLER_WRITE' => array( + '5.3' => false, + '5.4' => true, + ), + // Sessions: + 'PHP_SESSION_ACTIVE' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_SESSION_DISABLED' => array( + '5.3' => false, + '5.4' => true, + ), + 'PHP_SESSION_NONE' => array( + '5.3' => false, + '5.4' => true, + ), + // Streams: + 'STREAM_META_ACCESS' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_GROUP' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_GROUP_NAME' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_OWNER' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_OWNER_NAME' => array( + '5.3' => false, + '5.4' => true, + ), + 'STREAM_META_TOUCH' => array( + '5.3' => false, + '5.4' => true, + ), + // Intl: + 'U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_CHECK_BIDI' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_CHECK_CONTEXTJ' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_NONTRANSITIONAL_TO_ASCII' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_NONTRANSITIONAL_TO_UNICODE' => array( + '5.3' => false, + '5.4' => true, + ), + 'INTL_IDNA_VARIANT_2003' => array( + '5.3' => false, + '5.4' => true, + ), + 'INTL_IDNA_VARIANT_UTS46' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_EMPTY_LABEL' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LABEL_TOO_LONG' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_DOMAIN_NAME_TOO_LONG' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LEADING_HYPHEN' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_TRAILING_HYPHEN' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_HYPHEN_3_4' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LEADING_COMBINING_MARK' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_DISALLOWED' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_PUNYCODE' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_LABEL_HAS_DOT' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_INVALID_ACE_LABEL' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_BIDI' => array( + '5.3' => false, + '5.4' => true, + ), + 'IDNA_ERROR_CONTEXTJ' => array( + '5.3' => false, + '5.4' => true, + ), + // Json: + 'JSON_PRETTY_PRINT' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_UNESCAPED_SLASHES' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_UNESCAPED_UNICODE' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_BIGINT_AS_STRING' => array( + '5.3' => false, + '5.4' => true, + ), + 'JSON_OBJECT_AS_ARRAY' => array( + '5.3' => false, + '5.4' => true, + ), + // Snmp: + 'SNMP_OID_OUTPUT_SUFFIX' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP_OID_OUTPUT_MODULE' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP_OID_OUTPUT_UCD' => array( + '5.3' => false, + '5.4' => true, + ), + 'SNMP_OID_OUTPUT_NONE' => array( + '5.3' => false, + '5.4' => true, + ), + // Tokenizer: + 'T_INSTEADOF' => array( + '5.3' => false, + '5.4' => true, + ), + 'T_TRAIT' => array( + '5.3' => false, + '5.4' => true, + ), + 'T_TRAIT_C' => array( + '5.3' => false, + '5.4' => true, + ), + + // Curl: + 'CURLINFO_PRIMARY_IP' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + 'CURLINFO_PRIMARY_PORT' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + 'CURLINFO_LOCAL_IP' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + 'CURLINFO_LOCAL_PORT' => array( + '5.4.6' => false, + '5.4.7' => true, + ), + + // OpenSSL: + 'OPENSSL_ALGO_RMD160' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA224' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA256' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA384' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + 'OPENSSL_ALGO_SHA512' => array( + '5.4.7' => false, + '5.4.8' => true, + ), + + // Filter: + 'FILTER_VALIDATE_MAC' => array( + '5.4' => false, + '5.5' => true, + ), + // GD + 'IMG_AFFINE_TRANSLATE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_SCALE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_ROTATE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_SHEAR_HORIZONTAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_AFFINE_SHEAR_VERTICAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_DEFAULT' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_TRANSPARENT' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_BLACK' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_WHITE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CROP_SIDES' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_FLIP_BOTH' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_FLIP_HORIZONTAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_FLIP_VERTICAL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BELL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BESSEL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BILINEAR_FIXED' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BICUBIC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BICUBIC_FIXED' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BLACKMAN' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BOX' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_BSPLINE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_CATMULLROM' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_GAUSSIAN' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_GENERALIZED_CUBIC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_HERMITE' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_HAMMING' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_HANNING' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_MITCHELL' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_POWER' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_QUADRATIC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_SINC' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_NEAREST_NEIGHBOUR' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_WEIGHTED4' => array( + '5.4' => false, + '5.5' => true, + ), + 'IMG_TRIANGLE' => array( + '5.4' => false, + '5.5' => true, + ), + // JSON: + 'JSON_ERROR_RECURSION' => array( + '5.4' => false, + '5.5' => true, + ), + 'JSON_ERROR_INF_OR_NAN' => array( + '5.4' => false, + '5.5' => true, + ), + 'JSON_ERROR_UNSUPPORTED_TYPE' => array( + '5.4' => false, + '5.5' => true, + ), + 'JSON_PARTIAL_OUTPUT_ON_ERROR' => array( + '5.4' => false, + '5.5' => true, + ), + // MySQLi + 'MYSQLI_SERVER_PUBLIC_KEY' => array( + '5.4' => false, + '5.5' => true, + ), + // Curl: + 'CURLOPT_SHARE' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLOPT_SSL_OPTIONS' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLSSLOPT_ALLOW_BEAST' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLOPT_USERNAME' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RESPONSE_CODE' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_HTTP_CONNECTCODE' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_HTTPAUTH_AVAIL' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_PROXYAUTH_AVAIL' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_OS_ERRNO' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_NUM_CONNECTS' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_SSL_ENGINES' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_COOKIELIST' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_FTP_ENTRY_PATH' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_APPCONNECT_TIME' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_CONDITION_UNMET' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_CLIENT_CSEQ' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_CSEQ_RECV' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_SERVER_CSEQ' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLINFO_RTSP_SESSION_ID' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLMOPT_PIPELINING' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLMOPT_MAXCONNECTS' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_ALL' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_CONT' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_RECV' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_RECV_CONT' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_SEND' => array( + '5.4' => false, + '5.5' => true, + ), + 'CURLPAUSE_SEND_CONT' => array( + '5.4' => false, + '5.5' => true, + ), + // Soap: + 'SOAP_SSL_METHOD_TLS' => array( + '5.4' => false, + '5.5' => true, + ), + 'SOAP_SSL_METHOD_SSLv2' => array( + '5.4' => false, + '5.5' => true, + ), + 'SOAP_SSL_METHOD_SSLv3' => array( + '5.4' => false, + '5.5' => true, + ), + 'SOAP_SSL_METHOD_SSLv23' => array( + '5.4' => false, + '5.5' => true, + ), + // Tokenizer: + 'T_FINALLY' => array( + '5.4' => false, + '5.5' => true, + ), + 'T_YIELD' => array( + '5.4' => false, + '5.5' => true, + ), + // Core/Password Hashing: + 'PASSWORD_BCRYPT' => array( + '5.4' => false, + '5.5' => true, + ), + 'PASSWORD_DEFAULT' => array( + '5.4' => false, + '5.5' => true, + ), + 'PASSWORD_BCRYPT_DEFAULT_COST' => array( + '5.4' => false, + '5.5' => true, + ), + + + // Libxml: + 'LIBXML_SCHEMA_CREATE' => array( + '5.5.1' => false, + '5.5.2' => true, + ), + + // Curl: + 'CURL_SSLVERSION_TLSv1_0' => array( + '5.5.18' => false, + '5.5.19' => true, + ), + 'CURL_SSLVERSION_TLSv1_1' => array( + '5.5.18' => false, + '5.5.19' => true, + ), + 'CURL_SSLVERSION_TLSv1_2' => array( + '5.5.18' => false, + '5.5.19' => true, + ), + + 'CURLPROXY_SOCKS4A' => array( + '5.5.22' => false, + '5.5.23' => true, + ), + 'CURLPROXY_SOCKS5_HOSTNAME' => array( + '5.5.22' => false, + '5.5.23' => true, + ), + + 'CURL_VERSION_HTTP2' => array( + '5.5.23' => false, + '5.5.24' => true, + ), + + 'ARRAY_FILTER_USE_KEY' => array( + '5.5' => false, + '5.6' => true, + ), + 'ARRAY_FILTER_USE_BOTH' => array( + '5.5' => false, + '5.6' => true, + ), + // LDAP: + 'LDAP_ESCAPE_DN' => array( + '5.5' => false, + '5.6' => true, + ), + 'LDAP_ESCAPE_FILTER' => array( + '5.5' => false, + '5.6' => true, + ), + // OpenSSL: + 'OPENSSL_DEFAULT_STREAM_CIPHERS' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_ANY_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_ANY_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_0_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_1_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT' => array( + '5.5' => false, + '5.6' => true, + ), + 'STREAM_CRYPTO_METHOD_TLSv1_2_SERVER' => array( + '5.5' => false, + '5.6' => true, + ), + // PostgreSQL: + 'PGSQL_CONNECT_ASYNC' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_AUTH_OK' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_AWAITING_RESPONSE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_MADE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_SETENV' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_SSL_STARTUP' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_CONNECTION_STARTED' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_DML_ESCAPE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_ACTIVE' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_FAILED' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_OK' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_READING' => array( + '5.5' => false, + '5.6' => true, + ), + 'PGSQL_POLLING_WRITING' => array( + '5.5' => false, + '5.6' => true, + ), + // Tokenizer: + 'T_ELLIPSIS' => array( + '5.5' => false, + '5.6' => true, + ), + 'T_POW' => array( + '5.5' => false, + '5.6' => true, + ), + 'T_POW_EQUAL' => array( + '5.5' => false, + '5.6' => true, + ), + + 'INI_SCANNER_TYPED' => array( + '5.6.0' => false, + '5.6.1' => true, + ), + + 'JSON_PRESERVE_ZERO_FRACTION' => array( + '5.6.5' => false, + '5.6.6' => true, + ), + + 'MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT' => array( + '5.6.15' => false, + '5.6.16' => true, + ), + + // GD: + // Also introduced in 7.0.10. + 'IMG_WEBP' => array( + '5.6.24' => false, + '5.6.25' => true, + ), + + + 'TOKEN_PARSE' => array( + '5.6' => false, + '7.0' => true, + ), + 'FILTER_VALIDATE_DOMAIN' => array( + '5.6' => false, + '7.0' => true, + ), + 'PHP_INT_MIN' => array( + '5.6' => false, + '7.0' => true, + ), + // Curl: + 'CURLPIPE_NOTHING' => array( + '5.6' => false, + '7.0' => true, + ), + 'CURLPIPE_HTTP1' => array( + '5.6' => false, + '7.0' => true, + ), + 'CURLPIPE_MULTIPLEX' => array( + '5.6' => false, + '7.0' => true, + ), + // JSON: + 'JSON_ERROR_INVALID_PROPERTY_NAME' => array( + '5.6' => false, + '7.0' => true, + ), + 'JSON_ERROR_UTF16' => array( + '5.6' => false, + '7.0' => true, + ), + // LibXML: + 'LIBXML_BIGLINES' => array( + '5.6' => false, + '7.0' => true, + ), + // PCRE: + 'PREG_JIT_STACKLIMIT_ERROR' => array( + '5.6' => false, + '7.0' => true, + ), + // POSIX: + 'POSIX_RLIMIT_AS' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_CORE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_CPU' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_DATA' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_FSIZE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_LOCKS' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_MEMLOCK' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_MSGQUEUE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_NICE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_NOFILE' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_NPROC' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_RSS' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_RTPRIO' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_RTTIME' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_SIGPENDING' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_STACK' => array( + '5.6' => false, + '7.0' => true, + ), + 'POSIX_RLIMIT_INFINITY' => array( + '5.6' => false, + '7.0' => true, + ), + // Tokenizer: + 'T_COALESCE' => array( + '5.6' => false, + '7.0' => true, + ), + 'T_SPACESHIP' => array( + '5.6' => false, + '7.0' => true, + ), + 'T_YIELD_FROM' => array( + '5.6' => false, + '7.0' => true, + ), + + // Zlib: + // The first three are in the PHP 5.4 changelog, but the Extension constant page says 7.0. + 'ZLIB_ENCODING_RAW' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_ENCODING_DEFLATE' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_ENCODING_GZIP' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FILTERED' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_HUFFMAN_ONLY' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FIXED' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_RLE' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_DEFAULT_STRATEGY' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_BLOCK' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FINISH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_FULL_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_NO_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_PARTIAL_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + 'ZLIB_SYNC_FLUSH' => array( + '5.6' => false, + '7.0' => true, + ), + + 'CURL_HTTP_VERSION_2' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_HTTP_VERSION_2TLS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_301' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_302' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_303' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_REDIR_POST_ALL' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_VERSION_KERBEROS5' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_VERSION_PSL' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURL_VERSION_UNIX_SOCKETS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLAUTH_NEGOTIATE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLAUTH_NTLM_WB' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLFTP_CREATE_DIR' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLFTP_CREATE_DIR_NONE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLFTP_CREATE_DIR_RETRY' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLHEADER_SEPARATE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLHEADER_UNIFIED' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_MAX_HOST_CONNECTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_MAX_PIPELINE_LENGTH' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLMOPT_MAX_TOTAL_CONNECTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_CONNECT_TO' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DEFAULT_PROTOCOL' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DNS_INTERFACE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DNS_LOCAL_IP4' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_DNS_LOCAL_IP6' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_EXPECT_100_TIMEOUT_MS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_HEADEROPT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_LOGIN_OPTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PATH_AS_IS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PINNEDPUBLICKEY' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PIPEWAIT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PROXY_SERVICE_NAME' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_PROXYHEADER' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SASL_IR' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SERVICE_NAME' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_ENABLE_ALPN' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_ENABLE_NPN' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_FALSESTART' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_SSL_VERIFYSTATUS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_STREAM_WEIGHT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_TCP_FASTOPEN' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_TFTP_NO_OPTIONS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_UNIX_SOCKET_PATH' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLOPT_XOAUTH2_BEARER' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLPROTO_SMB' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLPROTO_SMBS' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLPROXY_HTTP_1_0' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLSSH_AUTH_AGENT' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + 'CURLSSLOPT_NO_REVOKE' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + + 'PHP_FD_SETSIZE' => array( + '7.0' => false, + '7.1' => true, + ), + // Curl: + 'CURLMOPT_PUSHFUNCTION' => array( + '7.0' => false, + '7.1' => true, + ), + 'CURL_PUSH_OK' => array( + '7.0' => false, + '7.1' => true, + ), + 'CURL_PUSH_DENY' => array( + '7.0' => false, + '7.1' => true, + ), + // Filter: + 'FILTER_FLAG_EMAIL_UNICODE' => array( + '7.0' => false, + '7.1' => true, + ), + // GD: + 'IMAGETYPE_WEBP' => array( + '7.0' => false, + '7.1' => true, + ), + // Json: + 'JSON_UNESCAPED_LINE_TERMINATORS' => array( + '7.0' => false, + '7.1' => true, + ), + // LDAP: + 'LDAP_OPT_X_SASL_NOCANON' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_SASL_USERNAME' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CACERTDIR' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CACERTFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CERTFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CIPHER_SUITE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_KEYFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_RANDOM_FILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRLCHECK' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRL_NONE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRL_PEER' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRL_ALL' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_DHFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_CRLFILE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_MIN' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_SSL2' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_SSL3' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_0' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_1' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PROTOCOL_TLS1_2' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_TLS_PACKAGE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_KEEPALIVE_IDLE' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_KEEPALIVE_PROBES' => array( + '7.0' => false, + '7.1' => true, + ), + 'LDAP_OPT_X_KEEPALIVE_INTERVAL' => array( + '7.0' => false, + '7.1' => true, + ), + // PostgreSQL: + 'PGSQL_NOTICE_LAST' => array( + '7.0' => false, + '7.1' => true, + ), + 'PGSQL_NOTICE_ALL' => array( + '7.0' => false, + '7.1' => true, + ), + 'PGSQL_NOTICE_CLEAR' => array( + '7.0' => false, + '7.1' => true, + ), + // SPL: + 'MT_RAND_PHP' => array( + '7.0' => false, + '7.1' => true, + ), + + // SQLite3: + 'SQLITE3_DETERMINISTIC' => array( + '7.1.3' => false, + '7.1.4' => true, + ), + + // Core: + 'PHP_OS_FAMILY' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_DIG' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_EPSILON' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'PHP_FLOAT_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + + // Core/Password Hashing: + 'PASSWORD_ARGON2I' => array( + '7.1' => false, + '7.2' => true, + ), + 'PASSWORD_ARGON2_DEFAULT_MEMORY_COST' => array( + '7.1' => false, + '7.2' => true, + ), + 'PASSWORD_ARGON2_DEFAULT_TIME_COST' => array( + '7.1' => false, + '7.2' => true, + ), + 'PASSWORD_ARGON2_DEFAULT_THREADS' => array( + '7.1' => false, + '7.2' => true, + ), + + // Fileinfo: + 'FILEINFO_EXTENSION' => array( + '7.1' => false, + '7.2' => true, + ), + + // GD: + 'IMG_EFFECT_MULTIPLY' => array( + '7.1' => false, + '7.2' => true, + ), + 'IMG_BMP' => array( + '7.1' => false, + '7.2' => true, + ), + + // JSON: + 'JSON_INVALID_UTF8_IGNORE' => array( + '7.1' => false, + '7.2' => true, + ), + 'JSON_INVALID_UTF8_SUBSTITUTE' => array( + '7.1' => false, + '7.2' => true, + ), + + // LDAP: + 'LDAP_EXOP_START_TLS' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_MODIFY_PASSWD' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_REFRESH' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_WHO_AM_I' => array( + '7.1' => false, + '7.2' => true, + ), + 'LDAP_EXOP_TURN' => array( + '7.1' => false, + '7.2' => true, + ), + + // PCRE: + 'PREG_UNMATCHED_AS_NULL' => array( + '7.1' => false, + '7.2' => true, + ), + + // Sodium: + 'SODIUM_LIBRARY_VERSION' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_LIBRARY_MAJOR_VERSION' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_LIBRARY_MINOR_VERSION' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_ORIGINAL' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_URLSAFE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AUTH_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_AUTH_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_SEALBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_SECRETKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_PUBLICKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_KEYPAIRBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_MACBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_NONCEBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_BOX_SEEDBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_BYTES_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_BYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_CONTEXTBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KDF_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_SEEDBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_SESSIONKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_PUBLICKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_SECRETKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_KX_KEYPAIRBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_BYTES_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_BYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MIN' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_ALG_DEFAULT' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SALTBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_STRPREFIX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SCALARMULT_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SCALARMULT_SCALARBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SHORTHASH_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SHORTHASH_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETBOX_MACBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETBOX_NONCEBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_MESSAGE' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_BYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_SEEDBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_SECRETKEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_SIGN_KEYPAIRBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_STREAM_NONCEBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + 'SODIUM_CRYPTO_STREAM_KEYBYTES' => array( + '7.1' => false, + '7.2' => true, + ), + + 'CURLAUTH_BEARER' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLAUTH_GSSAPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLE_WEIRD_SERVER_REPLY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_APPCONNECT_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_CONNECT_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_CONTENT_LENGTH_DOWNLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_CONTENT_LENGTH_UPLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_FILETIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_HTTP_VERSION' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_NAMELOOKUP_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_PRETRANSFER_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_PROTOCOL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_PROXY_SSL_VERIFYRESULT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_REDIRECT_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SCHEME' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SIZE_DOWNLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SIZE_UPLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SPEED_DOWNLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_SPEED_UPLOAD_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_STARTTRANSFER_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLINFO_TOTAL_TIME_T' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_LOCK_DATA_CONNECT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_LOCK_DATA_PSL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_MAX_READ_SIZE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_ABSTRACT_UNIX_SOCKET' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_DISALLOW_USERNAME_IN_URL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_DNS_SHUFFLE_ADDRESSES' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_HAPROXYPROTOCOL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_KEEP_SENDING_ON_ERROR' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PRE_PROXY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_CAINFO' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_CAPATH' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_CRLFILE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_KEYPASSWD' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_PINNEDPUBLICKEY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLCERT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLCERTTYPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_CIPHER_LIST' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLKEY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLKEYTYPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_OPTIONS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_VERIFYHOST' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSL_VERIFYPEER' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_SSLVERSION' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLS13_CIPHERS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLSAUTH_PASSWORD' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLSAUTH_TYPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_PROXY_TLSAUTH_USERNAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_REQUEST_TARGET' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_SOCKS5_AUTH' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_SSH_COMPRESSION' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_SUPPRESS_CONNECT_HEADERS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_TIMEVALUE_LARGE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLOPT_TLS13_CIPHERS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLPROXY_HTTPS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURLSSH_AUTH_GSSAPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_DEFAULT' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_NONE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_0' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_1' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_2' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_MAX_TLSv1_3' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_SSLVERSION_TLSv1_3' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_ASYNCHDNS' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_BROTLI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_CONV' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_DEBUG' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_GSSAPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_GSSNEGOTIATE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_HTTPS_PROXY' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_IDN' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_LARGEFILE' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_MULTI_SSL' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_NTLM' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_NTLM_WB' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_SPNEGO' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_SSPI' => array( + '7.2' => false, + '7.3' => true, + ), + 'CURL_VERSION_TLSAUTH_SRP' => array( + '7.2' => false, + '7.3' => true, + ), + 'FILTER_SANITIZE_ADD_SLASHES' => array( + '7.2' => false, + '7.3' => true, + ), + 'JSON_THROW_ON_ERROR' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_MANAGEDSAIT' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PROXY_AUTHZ' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SUBENTRIES' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_VALUESRETURNFILTER' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_ASSERT' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PRE_READ' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_POST_READ' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SORTREQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SORTRESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PAGEDRESULTS' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_AUTHZID_REQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_AUTHZID_RESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SYNC' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SYNC_STATE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_SYNC_DONE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_DONTUSECOPY' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PASSWORDPOLICYREQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_PASSWORDPOLICYRESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_INCREMENTAL_VALUES' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_DOMAIN_SCOPE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_PERMISSIVE_MODIFY' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_SEARCH_OPTIONS' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_TREE_DELETE' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_X_EXTENDED_DN' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_VLVREQUEST' => array( + '7.2' => false, + '7.3' => true, + ), + 'LDAP_CONTROL_VLVRESPONSE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_FOLD' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_UPPER_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_LOWER_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_TITLE_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'MB_CASE_FOLD_SIMPLE' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_SCHEMA_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_TABLE_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_COLUMN_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_DATATYPE_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_CONSTRAINT_NAME' => array( + '7.2' => false, + '7.3' => true, + ), + 'PGSQL_DIAG_SEVERITY_NONLOCALIZED' => array( + '7.2' => false, + '7.3' => true, + ), + 'PASSWORD_ARGON2ID' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_SSLv3' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_TLSv1_0' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_TLSv1_1' => array( + '7.2' => false, + '7.3' => true, + ), + 'STREAM_CRYPTO_PROTO_TLSv1_2' => array( + '7.2' => false, + '7.3' => true, + ), + + 'CURL_VERSION_ALTSVC' => array( + '7.3.5' => false, + '7.3.6' => true, + ), + 'CURL_VERSION_CURLDEBUG' => array( + '7.3.5' => false, + '7.3.6' => true, + ), + + 'IMG_FILTER_SCATTER' => array( + '7.3' => false, + '7.4' => true, + ), + 'MB_ONIGURUMA_VERSION' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_LABEL' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_PEERLABEL' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_LISTENQLIMIT' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_LISTENQLEN' => array( + '7.3' => false, + '7.4' => true, + ), + 'SO_USER_COOKIE' => array( + '7.3' => false, + '7.4' => true, + ), + 'PASSWORD_ARGON2_PROVIDER' => array( + '7.3' => false, + '7.4' => true, + ), + 'PHP_WINDOWS_EVENT_CTRL_C' => array( + '7.3' => false, + '7.4' => true, + ), + 'PHP_WINDOWS_EVENT_CTRL_BREAK' => array( + '7.3' => false, + '7.4' => true, + ), + 'T_BAD_CHARACTER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_ARTICLE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_ASIDE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_AUDIO' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_BDI' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_CANVAS' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_COMMAND' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_DATALIST' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_DETAILS' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_DIALOG' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_FIGCAPTION' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_FIGURE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_FOOTER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_HEADER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_HGROUP' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_MAIN' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_MARK' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_MENUITEM' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_METER' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_NAV' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_OUTPUT' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_PROGRESS' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_SECTION' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_SOURCE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_SUMMARY' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_TEMPLATE' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_TIME' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_TRACK' => array( + '7.3' => false, + '7.4' => true, + ), + 'TIDY_TAG_VIDEO' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $constantName = $tokens[$stackPtr]['content']; + + if (isset($this->newConstants[$constantName]) === false) { + return; + } + + if ($this->isUseOfGlobalConstant($phpcsFile, $stackPtr) === false) { + return; + } + + $itemInfo = array( + 'name' => $constantName, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newConstants[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 8.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The constant "%s" is not present in PHP version %s or earlier'; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php new file mode 100644 index 000000000..ccd586410 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/NewMagicClassConstantSniff.php @@ -0,0 +1,80 @@ +supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (strtolower($tokens[$stackPtr]['content']) !== 'class') { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($prevToken === false || $tokens[$prevToken]['code'] !== \T_DOUBLE_COLON) { + return; + } + + $phpcsFile->addError( + 'The magic class constant ClassName::class was not available in PHP 5.4 or earlier', + $stackPtr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php new file mode 100644 index 000000000..b6c8f8d75 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Constants/RemovedConstantsSniff.php @@ -0,0 +1,574 @@ + array(string => bool|string)) + */ + protected $removedConstants = array( + // Disabled since PHP 5.3.0 due to thread safety issues. + 'FILEINFO_COMPRESS' => array( + '5.3' => true, + ), + + 'CURLOPT_CLOSEPOLICY' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_LEAST_RECENTLY_USED' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_LEAST_TRAFFIC' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_SLOWEST' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_CALLBACK' => array( + '5.6' => true, + ), + 'CURLCLOSEPOLICY_OLDEST' => array( + '5.6' => true, + ), + + 'PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT' => array( + '7.0' => true, + ), + 'T_CHARACTER' => array( + '7.0' => true, + ), + 'T_BAD_CHARACTER' => array( + '7.0' => true, + ), + + 'INTL_IDNA_VARIANT_2003' => array( + '7.2' => false, + ), + + 'MCRYPT_MODE_ECB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_CBC' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_CFB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_OFB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_NOFB' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MODE_STREAM' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ENCRYPT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DECRYPT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DEV_RANDOM' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DEV_URANDOM' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RAND' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_3DES' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ARCFOUR_IV' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ARCFOUR' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_BLOWFISH' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_CAST_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_CAST_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_CRYPT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DES' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_DES_COMPAT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_ENIGMA' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_GOST' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_IDEA' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_LOKI97' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_MARS' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_PANAMA' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RIJNDAEL_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RIJNDAEL_192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RIJNDAEL_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC2' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC4' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6_192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_RC6_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SAFER64' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SAFER128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SAFERPLUS' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT_128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT_192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SERPENT_256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_SKIPJACK' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TEAN' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_THREEWAY' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TRIPLEDES' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH128' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH192' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_TWOFISH256' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_WAKE' => array( + '7.1' => false, + '7.2' => true, + ), + 'MCRYPT_XTEA' => array( + '7.1' => false, + '7.2' => true, + ), + + 'PHPDBG_FILE' => array( + '7.3' => true, + ), + 'PHPDBG_METHOD' => array( + '7.3' => true, + ), + 'PHPDBG_LINENO' => array( + '7.3' => true, + ), + 'PHPDBG_FUNC' => array( + '7.3' => true, + ), + 'FILTER_FLAG_SCHEME_REQUIRED' => array( + '7.3' => false, + ), + 'FILTER_FLAG_HOST_REQUIRED' => array( + '7.3' => false, + ), + + 'CURLPIPE_HTTP1' => array( + '7.4' => false, + ), + 'FILTER_SANITIZE_MAGIC_QUOTES' => array( + '7.4' => false, + 'alternative' => 'FILTER_SANITIZE_ADD_SLASHES', + ), + 'IBASE_BKP_CONVERT' => array( + '7.4' => true, + ), + 'IBASE_BKP_IGNORE_CHECKSUMS' => array( + '7.4' => true, + ), + 'IBASE_BKP_IGNORE_LIMBO' => array( + '7.4' => true, + ), + 'IBASE_BKP_METADATA_ONLY' => array( + '7.4' => true, + ), + 'IBASE_BKP_NO_GARBAGE_COLLECT' => array( + '7.4' => true, + ), + 'IBASE_BKP_NON_TRANSPORTABLE' => array( + '7.4' => true, + ), + 'IBASE_BKP_OLD_DESCRIPTIONS' => array( + '7.4' => true, + ), + 'IBASE_COMMITTED' => array( + '7.4' => true, + ), + 'IBASE_CONCURRENCY' => array( + '7.4' => true, + ), + 'IBASE_CONSISTENCY' => array( + '7.4' => true, + ), + 'IBASE_DEFAULT' => array( + '7.4' => true, + ), + 'IBASE_FETCH_ARRAYS' => array( + '7.4' => true, + ), + 'IBASE_FETCH_BLOBS' => array( + '7.4' => true, + ), + 'IBASE_NOWAIT' => array( + '7.4' => true, + ), + 'IBASE_PRP_ACCESS_MODE' => array( + '7.4' => true, + ), + 'IBASE_PRP_ACTIVATE' => array( + '7.4' => true, + ), + 'IBASE_PRP_AM_READONLY' => array( + '7.4' => true, + ), + 'IBASE_PRP_AM_READWRITE' => array( + '7.4' => true, + ), + 'IBASE_PRP_DENY_NEW_ATTACHMENTS' => array( + '7.4' => true, + ), + 'IBASE_PRP_DENY_NEW_TRANSACTIONS' => array( + '7.4' => true, + ), + 'IBASE_PRP_DB_ONLINE' => array( + '7.4' => true, + ), + 'IBASE_PRP_PAGE_BUFFERS' => array( + '7.4' => true, + ), + 'IBASE_PRP_RES' => array( + '7.4' => true, + ), + 'IBASE_PRP_RES_USE_FULL' => array( + '7.4' => true, + ), + 'IBASE_PRP_RESERVE_SPACE' => array( + '7.4' => true, + ), + 'IBASE_PRP_SET_SQL_DIALECT' => array( + '7.4' => true, + ), + 'IBASE_PRP_SHUTDOWN_DB' => array( + '7.4' => true, + ), + 'IBASE_PRP_SWEEP_INTERVAL' => array( + '7.4' => true, + ), + 'IBASE_PRP_WM_ASYNC' => array( + '7.4' => true, + ), + 'IBASE_PRP_WM_SYNC' => array( + '7.4' => true, + ), + 'IBASE_PRP_WRITE_MODE' => array( + '7.4' => true, + ), + 'IBASE_READ' => array( + '7.4' => true, + ), + 'IBASE_RES_CREATE' => array( + '7.4' => true, + ), + 'IBASE_RES_DEACTIVATE_IDX' => array( + '7.4' => true, + ), + 'IBASE_RES_NO_SHADOW' => array( + '7.4' => true, + ), + 'IBASE_RES_NO_VALIDITY' => array( + '7.4' => true, + ), + 'IBASE_RES_ONE_AT_A_TIME' => array( + '7.4' => true, + ), + 'IBASE_RES_REPLACE' => array( + '7.4' => true, + ), + 'IBASE_RES_USE_ALL_SPACE' => array( + '7.4' => true, + ), + 'IBASE_RPR_CHECK_DB' => array( + '7.4' => true, + ), + 'IBASE_RPR_FULL' => array( + '7.4' => true, + ), + 'IBASE_RPR_IGNORE_CHECKSUM' => array( + '7.4' => true, + ), + 'IBASE_RPR_KILL_SHADOWS' => array( + '7.4' => true, + ), + 'IBASE_RPR_MEND_DB' => array( + '7.4' => true, + ), + 'IBASE_RPR_SWEEP_DB' => array( + '7.4' => true, + ), + 'IBASE_RPR_VALIDATE_DB' => array( + '7.4' => true, + ), + 'IBASE_STS_DATA_PAGES' => array( + '7.4' => true, + ), + 'IBASE_STS_DB_LOG' => array( + '7.4' => true, + ), + 'IBASE_STS_HDR_PAGES' => array( + '7.4' => true, + ), + 'IBASE_STS_IDX_PAGES' => array( + '7.4' => true, + ), + 'IBASE_STS_SYS_RELATIONS' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_ENV' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_ENV_LOCK' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_ENV_MSG' => array( + '7.4' => true, + ), + 'IBASE_SVC_GET_USERS' => array( + '7.4' => true, + ), + 'IBASE_SVC_IMPLEMENTATION' => array( + '7.4' => true, + ), + 'IBASE_SVC_SERVER_VERSION' => array( + '7.4' => true, + ), + 'IBASE_SVC_SVR_DB_INFO' => array( + '7.4' => true, + ), + 'IBASE_SVC_USER_DBPATH' => array( + '7.4' => true, + ), + 'IBASE_UNIXTIME' => array( + '7.4' => true, + ), + 'IBASE_WAIT' => array( + '7.4' => true, + ), + 'IBASE_WRITE' => array( + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $constantName = $tokens[$stackPtr]['content']; + + if (isset($this->removedConstants[$constantName]) === false) { + return; + } + + if ($this->isUseOfGlobalConstant($phpcsFile, $stackPtr) === false) { + return; + } + + $itemInfo = array( + 'name' => $constantName, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedConstants[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 8.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The constant "%s" is '; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php new file mode 100644 index 000000000..8d56b93a0 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/DiscouragedSwitchContinueSniff.php @@ -0,0 +1,238 @@ + \T_FOR, + \T_FOREACH => \T_FOREACH, + \T_WHILE => \T_WHILE, + \T_DO => \T_DO, + \T_SWITCH => \T_SWITCH, + ); + + /** + * Tokens which start a new case within a switch. + * + * @since 8.2.0 + * + * @var array + */ + protected $caseTokens = array( + \T_CASE => \T_CASE, + \T_DEFAULT => \T_DEFAULT, + ); + + /** + * Token codes which are accepted to determine the level for the continue. + * + * This array is enriched with the arithmetic operators in the register() method. + * + * @since 8.2.0 + * + * @var array + */ + protected $acceptedLevelTokens = array( + \T_LNUMBER => \T_LNUMBER, + \T_OPEN_PARENTHESIS => \T_OPEN_PARENTHESIS, + \T_CLOSE_PARENTHESIS => \T_CLOSE_PARENTHESIS, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + $this->acceptedLevelTokens += Tokens::$arithmeticTokens; + $this->acceptedLevelTokens += Tokens::$emptyTokens; + + return array(\T_SWITCH); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $switchOpener = $tokens[$stackPtr]['scope_opener']; + $switchCloser = $tokens[$stackPtr]['scope_closer']; + + // Quick check whether we need to bother with the more complex logic. + $hasContinue = $phpcsFile->findNext(\T_CONTINUE, ($switchOpener + 1), $switchCloser); + if ($hasContinue === false) { + return; + } + + $caseDefault = $switchOpener; + + do { + $caseDefault = $phpcsFile->findNext($this->caseTokens, ($caseDefault + 1), $switchCloser); + if ($caseDefault === false) { + break; + } + + if (isset($tokens[$caseDefault]['scope_opener']) === false) { + // Unknown start of the case, skip. + continue; + } + + $caseOpener = $tokens[$caseDefault]['scope_opener']; + $nextCaseDefault = $phpcsFile->findNext($this->caseTokens, ($caseDefault + 1), $switchCloser); + if ($nextCaseDefault === false) { + $caseCloser = $switchCloser; + } else { + $caseCloser = $nextCaseDefault; + } + + // Check for unscoped control structures within the case. + $controlStructure = $caseOpener; + $doCount = 0; + while (($controlStructure = $phpcsFile->findNext($this->loopStructures, ($controlStructure + 1), $caseCloser)) !== false) { + if ($tokens[$controlStructure]['code'] === \T_DO) { + $doCount++; + } + + if (isset($tokens[$controlStructure]['scope_opener'], $tokens[$controlStructure]['scope_closer']) === false) { + if ($tokens[$controlStructure]['code'] === \T_WHILE && $doCount > 0) { + // While in a do-while construct. + $doCount--; + continue; + } + + // Control structure without braces found within the case, ignore this case. + continue 2; + } + } + + // Examine the contents of the case. + $continue = $caseOpener; + + do { + $continue = $phpcsFile->findNext(\T_CONTINUE, ($continue + 1), $caseCloser); + if ($continue === false) { + break; + } + + $nextSemicolon = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($continue + 1), $caseCloser); + $codeString = ''; + for ($i = ($continue + 1); $i < $nextSemicolon; $i++) { + if (isset($this->acceptedLevelTokens[$tokens[$i]['code']]) === false) { + // Function call/variable or other token which make numeric level impossible to determine. + continue 2; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $codeString .= $tokens[$i]['content']; + } + + $level = null; + if ($codeString !== '') { + if (is_numeric($codeString)) { + $level = (int) $codeString; + } else { + // With the above logic, the string can only contain digits and operators, eval! + $level = eval("return ( $codeString );"); + } + } + + if (isset($level) === false || $level === 0) { + $level = 1; + } + + // Examine which control structure is being targeted by the continue statement. + if (isset($tokens[$continue]['conditions']) === false) { + continue; + } + + $conditions = array_reverse($tokens[$continue]['conditions'], true); + // PHPCS adds more structures to the conditions array than we want to take into + // consideration, so clean up the array. + foreach ($conditions as $tokenPtr => $tokenCode) { + if (isset($this->loopStructures[$tokenCode]) === false) { + unset($conditions[$tokenPtr]); + } + } + + $targetCondition = \array_slice($conditions, ($level - 1), 1, true); + if (empty($targetCondition)) { + continue; + } + + $conditionToken = key($targetCondition); + if ($conditionToken === $stackPtr) { + $phpcsFile->addWarning( + "Targeting a 'switch' control structure with a 'continue' statement is strongly discouraged and will throw a warning as of PHP 7.3.", + $continue, + 'Found' + ); + } + + } while ($continue < $caseCloser); + + } while ($caseDefault < $switchCloser); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php new file mode 100644 index 000000000..2cfbcc53d --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueOutsideLoopSniff.php @@ -0,0 +1,116 @@ + true, + \T_FOREACH => true, + \T_WHILE => true, + \T_DO => true, + \T_SWITCH => true, + ); + + /** + * Token codes which did not correctly get a condition assigned in older PHPCS versions. + * + * @since 7.0.7 + * + * @var array + */ + protected $backCompat = array( + \T_CASE => true, + \T_DEFAULT => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + return array( + \T_BREAK, + \T_CONTINUE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Check if the break/continue is within a valid loop structure. + if (empty($token['conditions']) === false) { + foreach ($token['conditions'] as $tokenCode) { + if (isset($this->validLoopStructures[$tokenCode]) === true) { + return; + } + } + } else { + // Deal with older PHPCS versions. + if (isset($token['scope_condition']) === true && isset($this->backCompat[$tokens[$token['scope_condition']]['code']]) === true) { + return; + } + } + + // If we're still here, no valid loop structure container has been found, so throw an error. + $error = "Using '%s' outside of a loop or switch structure is invalid"; + $isError = false; + $errorCode = 'Found'; + $data = array($token['content']); + + if ($this->supportsAbove('7.0')) { + $error .= ' and will throw a fatal error since PHP 7.0'; + $isError = true; + $errorCode = 'FatalError'; + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php new file mode 100644 index 000000000..f63c84883 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenBreakContinueVariableArgumentsSniff.php @@ -0,0 +1,110 @@ + 'a variable argument', + 'zeroArgument' => '0 as an argument', + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_BREAK, \T_CONTINUE); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextSemicolonToken = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr), null, false); + $errorType = ''; + for ($curToken = $stackPtr + 1; $curToken < $nextSemicolonToken; $curToken++) { + if ($tokens[$curToken]['type'] === 'T_STRING') { + // If the next non-whitespace token after the string + // is an opening parenthesis then it's a function call. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, $curToken + 1, null, true); + if ($tokens[$openBracket]['code'] === \T_OPEN_PARENTHESIS) { + $errorType = 'variableArgument'; + break; + } + + } elseif (\in_array($tokens[$curToken]['type'], array('T_VARIABLE', 'T_FUNCTION', 'T_CLOSURE'), true)) { + $errorType = 'variableArgument'; + break; + + } elseif ($tokens[$curToken]['type'] === 'T_LNUMBER' && $tokens[$curToken]['content'] === '0') { + $errorType = 'zeroArgument'; + break; + } + } + + if ($errorType !== '') { + $error = 'Using %s on break or continue is forbidden since PHP 5.4'; + $errorCode = $errorType . 'Found'; + $data = array($this->errorTypes[$errorType]); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php new file mode 100644 index 000000000..26f41c07e --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/ForbiddenSwitchWithMultipleDefaultBlocksSniff.php @@ -0,0 +1,81 @@ +supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $defaultToken = $stackPtr; + $defaultCount = 0; + $targetLevel = $tokens[$stackPtr]['level'] + 1; + while ($defaultCount < 2 && ($defaultToken = $phpcsFile->findNext(array(\T_DEFAULT), $defaultToken + 1, $tokens[$stackPtr]['scope_closer'])) !== false) { + // Same level or one below (= two default cases after each other). + if ($tokens[$defaultToken]['level'] === $targetLevel || $tokens[$defaultToken]['level'] === ($targetLevel + 1)) { + $defaultCount++; + } + } + + if ($defaultCount > 1) { + $phpcsFile->addError( + 'Switch statements can not have multiple default blocks since PHP 7.0', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php new file mode 100644 index 000000000..0e71a2612 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewExecutionDirectivesSniff.php @@ -0,0 +1,378 @@ + array(string => bool|string|array)) + */ + protected $newDirectives = array( + 'ticks' => array( + '3.1' => false, + '4.0' => true, + 'valid_value_callback' => 'isNumeric', + ), + 'encoding' => array( + '5.2' => false, + '5.3' => '--enable-zend-multibyte', // Directive ignored unless. + '5.4' => true, + 'valid_value_callback' => 'validEncoding', + ), + 'strict_types' => array( + '5.6' => false, + '7.0' => true, + 'valid_values' => array(1), + ), + ); + + + /** + * Tokens to ignore when trying to find the value for the directive. + * + * @since 7.0.3 + * + * @var array + */ + protected $ignoreTokens = array(); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + $this->ignoreTokens = Tokens::$emptyTokens; + $this->ignoreTokens[\T_EQUAL] = \T_EQUAL; + + return array(\T_DECLARE); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === true) { + $openParenthesis = $tokens[$stackPtr]['parenthesis_opener']; + $closeParenthesis = $tokens[$stackPtr]['parenthesis_closer']; + } else { + if (version_compare(PHPCSHelper::getVersion(), '2.3.4', '>=')) { + return; + } + + // Deal with PHPCS 2.3.0-2.3.3 which do not yet set the parenthesis properly for declare statements. + $openParenthesis = $phpcsFile->findNext(\T_OPEN_PARENTHESIS, ($stackPtr + 1), null, false, null, true); + if ($openParenthesis === false || isset($tokens[$openParenthesis]['parenthesis_closer']) === false) { + return; + } + $closeParenthesis = $tokens[$openParenthesis]['parenthesis_closer']; + } + + $directivePtr = $phpcsFile->findNext(\T_STRING, ($openParenthesis + 1), $closeParenthesis, false); + if ($directivePtr === false) { + return; + } + + $directiveContent = $tokens[$directivePtr]['content']; + + if (isset($this->newDirectives[$directiveContent]) === false) { + $error = 'Declare can only be used with the directives %s. Found: %s'; + $data = array( + implode(', ', array_keys($this->newDirectives)), + $directiveContent, + ); + + $phpcsFile->addError($error, $stackPtr, 'InvalidDirectiveFound', $data); + + } else { + // Check for valid directive for version. + $itemInfo = array( + 'name' => $directiveContent, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + + // Check for valid directive value. + $valuePtr = $phpcsFile->findNext($this->ignoreTokens, $directivePtr + 1, $closeParenthesis, true); + if ($valuePtr === false) { + return; + } + + $this->addWarningOnInvalidValue($phpcsFile, $valuePtr, $directiveContent); + } + } + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['not_in_version'] !== '' || $errorInfo['conditional_version'] !== ''); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newDirectives[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array( + 'valid_value_callback', + 'valid_values', + ); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['conditional_version'] = ''; + $errorInfo['condition'] = ''; + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $present) { + if (\is_string($present) === true && $this->supportsBelow($version) === true) { + // We cannot test for compilation option (ok, except by scraping the output of phpinfo...). + $errorInfo['conditional_version'] = $version; + $errorInfo['condition'] = $present; + } + } + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'Directive ' . parent::getErrorMsgTemplate(); + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.0.3 + * @since 7.1.0 This method now overloads the method from the `AbstractNewFeatureSniff` class. + * - Renamed from `maybeAddError()` to `addError()`. + * - Changed visibility from `protected` to `public`. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + if ($errorInfo['not_in_version'] !== '') { + parent::addError($phpcsFile, $stackPtr, $itemInfo, $errorInfo); + } elseif ($errorInfo['conditional_version'] !== '') { + $error = 'Directive %s is present in PHP version %s but will be disregarded unless PHP is compiled with %s'; + $errorCode = $this->stringToErrorCode($itemInfo['name']) . 'WithConditionFound'; + $data = array( + $itemInfo['name'], + $errorInfo['conditional_version'], + $errorInfo['condition'], + ); + + $phpcsFile->addWarning($error, $stackPtr, $errorCode, $data); + } + } + + + /** + * Generates a error or warning for this sniff. + * + * @since 7.0.3 + * @since 7.0.6 Renamed from `addErrorOnInvalidValue()` to `addWarningOnInvalidValue()`. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the execution directive value + * in the token array. + * @param string $directive The directive. + * + * @return void + */ + protected function addWarningOnInvalidValue(File $phpcsFile, $stackPtr, $directive) + { + $tokens = $phpcsFile->getTokens(); + + $value = $tokens[$stackPtr]['content']; + if (isset(Tokens::$stringTokens[$tokens[$stackPtr]['code']]) === true) { + $value = $this->stripQuotes($value); + } + + $isError = false; + if (isset($this->newDirectives[$directive]['valid_values'])) { + if (\in_array($value, $this->newDirectives[$directive]['valid_values']) === false) { + $isError = true; + } + } elseif (isset($this->newDirectives[$directive]['valid_value_callback'])) { + $valid = \call_user_func(array($this, $this->newDirectives[$directive]['valid_value_callback']), $value); + if ($valid === false) { + $isError = true; + } + } + + if ($isError === true) { + $error = 'The execution directive %s does not seem to have a valid value. Please review. Found: %s'; + $errorCode = $this->stringToErrorCode($directive) . 'InvalidValueFound'; + $data = array( + $directive, + $value, + ); + + $phpcsFile->addWarning($error, $stackPtr, $errorCode, $data); + } + } + + + /** + * Check whether a value is numeric. + * + * Callback function to test whether the value for an execution directive is valid. + * + * @since 7.0.3 + * + * @param mixed $value The value to test. + * + * @return bool + */ + protected function isNumeric($value) + { + return is_numeric($value); + } + + + /** + * Check whether a value is a valid encoding. + * + * Callback function to test whether the value for an execution directive is valid. + * + * @since 7.0.3 + * + * @param mixed $value The value to test. + * + * @return bool + */ + protected function validEncoding($value) + { + static $encodings; + if (isset($encodings) === false && function_exists('mb_list_encodings')) { + $encodings = mb_list_encodings(); + } + + if (empty($encodings) || \is_array($encodings) === false) { + // If we can't test the encoding, let it pass through. + return true; + } + + return \in_array($value, $encodings, true); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php new file mode 100644 index 000000000..a22276922 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewForeachExpressionReferencingSniff.php @@ -0,0 +1,99 @@ +supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $asToken = $phpcsFile->findNext(\T_AS, ($opener + 1), $closer); + if ($asToken === false) { + return; + } + + /* + * Note: referencing $key is not allowed in any version, so this should only find referenced $values. + * If it does find a referenced key, it would be a parse error anyway. + */ + $hasReference = $phpcsFile->findNext(\T_BITWISE_AND, ($asToken + 1), $closer); + if ($hasReference === false) { + return; + } + + $nestingLevel = 0; + if ($asToken !== ($opener + 1) && isset($tokens[$opener + 1]['nested_parenthesis'])) { + $nestingLevel = \count($tokens[$opener + 1]['nested_parenthesis']); + } + + if ($this->isVariable($phpcsFile, ($opener + 1), $asToken, $nestingLevel) === true) { + return; + } + + // Non-variable detected before the `as` keyword. + $phpcsFile->addError( + 'Referencing $value is only possible if the iterated array is a variable in PHP 5.4 or earlier.', + $hasReference, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php new file mode 100644 index 000000000..2398cf172 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewListInForeachSniff.php @@ -0,0 +1,84 @@ +supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $asToken = $phpcsFile->findNext(\T_AS, ($opener + 1), $closer); + if ($asToken === false) { + return; + } + + $hasList = $phpcsFile->findNext(array(\T_LIST, \T_OPEN_SHORT_ARRAY), ($asToken + 1), $closer); + if ($hasList === false) { + return; + } + + $phpcsFile->addError( + 'Unpacking nested arrays with list() in a foreach is not supported in PHP 5.4 or earlier.', + $hasList, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php new file mode 100644 index 000000000..256f37ff1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ControlStructures/NewMultiCatchSniff.php @@ -0,0 +1,78 @@ +supportsBelow('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Bow out during live coding. + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $hasBitwiseOr = $phpcsFile->findNext(\T_BITWISE_OR, $token['parenthesis_opener'], $token['parenthesis_closer']); + + if ($hasBitwiseOr === false) { + return; + } + + $phpcsFile->addError( + 'Catching multiple exceptions within one statement is not supported in PHP 7.0 or earlier.', + $hasBitwiseOr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php new file mode 100644 index 000000000..13f5dfce5 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Extensions/RemovedExtensionsSniff.php @@ -0,0 +1,346 @@ + + * + * + * + * + * + * @since 7.0.2 + * + * @var array + */ + public $functionWhitelist; + + /** + * A list of removed extensions with their alternative, if any. + * + * The array lists : version number with false (deprecated) and true (removed). + * If's sufficient to list the first version where the extension was deprecated/removed. + * + * @since 5.5 + * + * @var array(string => array(string => bool|string|null)) + */ + protected $removedExtensions = array( + 'activescript' => array( + '5.1' => true, + 'alternative' => 'pecl/activescript', + ), + 'cpdf' => array( + '5.1' => true, + 'alternative' => 'pecl/pdflib', + ), + 'dbase' => array( + '5.3' => true, + 'alternative' => null, + ), + 'dbx' => array( + '5.1' => true, + 'alternative' => 'pecl/dbx', + ), + 'dio' => array( + '5.1' => true, + 'alternative' => 'pecl/dio', + ), + 'ereg' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'pcre', + ), + 'fam' => array( + '5.1' => true, + 'alternative' => null, + ), + 'fbsql' => array( + '5.3' => true, + 'alternative' => null, + ), + 'fdf' => array( + '5.3' => true, + 'alternative' => 'pecl/fdf', + ), + 'filepro' => array( + '5.2' => true, + 'alternative' => null, + ), + 'hw_api' => array( + '5.2' => true, + 'alternative' => null, + ), + 'ibase' => array( + '7.4' => true, + 'alternative' => 'pecl/ibase', + ), + 'ingres' => array( + '5.1' => true, + 'alternative' => 'pecl/ingres', + ), + 'ircg' => array( + '5.1' => true, + 'alternative' => null, + ), + 'mcrypt' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'openssl (preferred) or pecl/mcrypt once available', + ), + 'mcve' => array( + '5.1' => true, + 'alternative' => 'pecl/mcve', + ), + 'ming' => array( + '5.3' => true, + 'alternative' => 'pecl/ming', + ), + 'mnogosearch' => array( + '5.1' => true, + 'alternative' => null, + ), + 'msql' => array( + '5.3' => true, + 'alternative' => null, + ), + 'mssql' => array( + '7.0' => true, + 'alternative' => null, + ), + 'mysql_' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => 'mysqli', + ), + 'ncurses' => array( + '5.3' => true, + 'alternative' => 'pecl/ncurses', + ), + 'oracle' => array( + '5.1' => true, + 'alternative' => 'oci8 or pdo_oci', + ), + 'ovrimos' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_' => array( + '5.1' => true, + 'alternative' => null, + ), + 'recode' => array( + '7.4' => true, + 'alternative' => 'iconv or mbstring', + ), + 'sqlite' => array( + '5.4' => true, + 'alternative' => null, + ), + // Has to be before `sybase` as otherwise it will never match. + 'sybase_ct' => array( + '7.0' => true, + 'alternative' => null, + ), + 'sybase' => array( + '5.3' => true, + 'alternative' => 'sybase_ct', + ), + 'w32api' => array( + '5.1' => true, + 'alternative' => 'pecl/ffi', + ), + 'wddx' => array( + '7.4' => true, + 'alternative' => 'pecl/wddx', + ), + 'yp' => array( + '5.1' => true, + 'alternative' => null, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->removedExtensions = $this->arrayKeysToLowercase($this->removedExtensions); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the next non-empty token. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$openBracket]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + // Not a function call. + return; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = \T_BITWISE_AND; + $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true); + if ($tokens[$previous]['code'] === \T_FUNCTION) { + // It's a function definition, not a function call. + return; + } + + if ($tokens[$previous]['code'] === \T_NEW) { + // We are creating an object, not calling a function. + return; + } + + if ($tokens[$previous]['code'] === \T_OBJECT_OPERATOR) { + // We are calling a method of an object. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if ($this->isWhiteListed($functionLc) === true) { + // Function is whitelisted. + return; + } + + foreach ($this->removedExtensions as $extension => $versionList) { + if (strpos($functionLc, $extension) === 0) { + $itemInfo = array( + 'name' => $extension, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + break; + } + } + } + + + /** + * Is the current function being checked whitelisted ? + * + * Parsing the list late as it may be provided as a property, but also inline. + * + * @since 7.0.2 + * + * @param string $content Content of the current token. + * + * @return bool + */ + protected function isWhiteListed($content) + { + if (isset($this->functionWhitelist) === false) { + return false; + } + + if (\is_string($this->functionWhitelist) === true) { + if (strpos($this->functionWhitelist, ',') !== false) { + $this->functionWhitelist = explode(',', $this->functionWhitelist); + } else { + $this->functionWhitelist = (array) $this->functionWhitelist; + } + } + + if (\is_array($this->functionWhitelist) === true) { + $this->functionWhitelist = array_map('strtolower', $this->functionWhitelist); + return \in_array($content, $this->functionWhitelist, true); + } + + return false; + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedExtensions[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "Extension '%s' is "; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php new file mode 100644 index 000000000..0f52af710 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParameterShadowSuperGlobalsSniff.php @@ -0,0 +1,79 @@ +supportsAbove('5.4') === false) { + return; + } + + // Get all parameters from function signature. + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($parameters) || \is_array($parameters) === false) { + return; + } + + foreach ($parameters as $param) { + if (isset($this->superglobals[$param['name']]) === true) { + $error = 'Parameter shadowing super global (%s) causes fatal error since PHP 5.4'; + $errorCode = $this->stringToErrorCode(substr($param['name'], 1)) . 'Found'; + $data = array($param['name']); + + $phpcsFile->addError($error, $param['token'], $errorCode, $data); + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php new file mode 100644 index 000000000..e94461ca6 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenParametersWithSameNameSniff.php @@ -0,0 +1,88 @@ +supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + // Skip function without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Get all parameters from method signature. + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($parameters) || \is_array($parameters) === false) { + return; + } + + $paramNames = array(); + foreach ($parameters as $param) { + $paramNames[] = $param['name']; + } + + if (\count($paramNames) !== \count(array_unique($paramNames))) { + $phpcsFile->addError( + 'Functions can not have multiple parameters with the same name since PHP 7.0', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php new file mode 100644 index 000000000..1625a4fa1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenToStringParametersSniff.php @@ -0,0 +1,99 @@ + true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if (strtolower($functionName) !== '__tostring') { + // Not the right function. + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) === false) { + // Function, not method. + return; + } + + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + // Function declared without parameters. + return; + } + + $phpcsFile->addError( + 'The __toString() magic method can no longer accept arguments since PHP 5.3', + $stackPtr, + 'Declared' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php new file mode 100644 index 000000000..2e72c05eb --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/ForbiddenVariableNamesInClosureUseSniff.php @@ -0,0 +1,122 @@ +supportsAbove('7.1') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Verify this use statement is used with a closure - if so, it has to have parenthesis before it. + $previousNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($previousNonEmpty === false || $tokens[$previousNonEmpty]['code'] !== \T_CLOSE_PARENTHESIS + || isset($tokens[$previousNonEmpty]['parenthesis_opener']) === false + ) { + return; + } + + // ... and (a variable within) parenthesis after it. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false) { + // Live coding. + return; + } + + $closurePtr = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($tokens[$previousNonEmpty]['parenthesis_opener'] - 1), null, true); + if ($closurePtr === false || $tokens[$closurePtr]['code'] !== \T_CLOSURE) { + return; + } + + // Get the parameters declared by the closure. + $closureParams = PHPCSHelper::getMethodParameters($phpcsFile, $closurePtr); + + $errorMsg = 'Variables bound to a closure via the use construct cannot use the same name as superglobals, $this, or a declared parameter since PHP 7.1. Found: %s'; + + for ($i = ($nextNonEmpty + 1); $i < $tokens[$nextNonEmpty]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== \T_VARIABLE) { + continue; + } + + $variableName = $tokens[$i]['content']; + + if ($variableName === '$this') { + $phpcsFile->addError($errorMsg, $i, 'FoundThis', array($variableName)); + continue; + } + + if (isset($this->superglobals[$variableName]) === true) { + $phpcsFile->addError($errorMsg, $i, 'FoundSuperglobal', array($variableName)); + continue; + } + + // Check whether it is one of the parameters declared by the closure. + if (empty($closureParams) === false) { + foreach ($closureParams as $param) { + if ($param['name'] === $variableName) { + $phpcsFile->addError($errorMsg, $i, 'FoundShadowParam', array($variableName)); + continue 2; + } + } + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php new file mode 100644 index 000000000..b71bb3201 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewClosureSniff.php @@ -0,0 +1,264 @@ +supportsBelow('5.2')) { + $phpcsFile->addError( + 'Closures / anonymous functions are not available in PHP 5.2 or earlier', + $stackPtr, + 'Found' + ); + } + + /* + * Closures can only be declared as static since PHP 5.4. + */ + $isStatic = $this->isClosureStatic($phpcsFile, $stackPtr); + if ($this->supportsBelow('5.3') && $isStatic === true) { + $phpcsFile->addError( + 'Closures / anonymous functions could not be declared as static in PHP 5.3 or earlier', + $stackPtr, + 'StaticFound' + ); + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + // Live coding or parse error. + return; + } + + $scopeStart = ($tokens[$stackPtr]['scope_opener'] + 1); + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + $usesThis = $this->findThisUsageInClosure($phpcsFile, $scopeStart, $scopeEnd); + + if ($this->supportsBelow('5.3')) { + /* + * Closures declared within classes only have access to $this since PHP 5.4. + */ + if ($usesThis !== false) { + $thisFound = $usesThis; + do { + $phpcsFile->addError( + 'Closures / anonymous functions did not have access to $this in PHP 5.3 or earlier', + $thisFound, + 'ThisFound' + ); + + $thisFound = $this->findThisUsageInClosure($phpcsFile, ($thisFound + 1), $scopeEnd); + + } while ($thisFound !== false); + } + + /* + * Closures declared within classes only have access to self/parent/static since PHP 5.4. + */ + $usesClassRef = $this->findClassRefUsageInClosure($phpcsFile, $scopeStart, $scopeEnd); + + if ($usesClassRef !== false) { + do { + $phpcsFile->addError( + 'Closures / anonymous functions could not use "%s::" in PHP 5.3 or earlier', + $usesClassRef, + 'ClassRefFound', + array(strtolower($tokens[$usesClassRef]['content'])) + ); + + $usesClassRef = $this->findClassRefUsageInClosure($phpcsFile, ($usesClassRef + 1), $scopeEnd); + + } while ($usesClassRef !== false); + } + } + + /* + * Check for correct usage. + */ + if ($this->supportsAbove('5.4') && $usesThis !== false) { + + $thisFound = $usesThis; + + do { + /* + * Closures only have access to $this if not declared as static. + */ + if ($isStatic === true) { + $phpcsFile->addError( + 'Closures / anonymous functions declared as static do not have access to $this', + $thisFound, + 'ThisFoundInStatic' + ); + } + + /* + * Closures only have access to $this if used within a class context. + */ + elseif ($this->inClassScope($phpcsFile, $stackPtr, false) === false) { + $phpcsFile->addWarning( + 'Closures / anonymous functions only have access to $this if used within a class or when bound to an object using bindTo(). Please verify.', + $thisFound, + 'ThisFoundOutsideClass' + ); + } + + $thisFound = $this->findThisUsageInClosure($phpcsFile, ($thisFound + 1), $scopeEnd); + + } while ($thisFound !== false); + } + + // Prevent double reporting for nested closures. + return $scopeEnd; + } + + + /** + * Check whether the closure is declared as static. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return bool + */ + protected function isClosureStatic(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + + return ($prevToken !== false && $tokens[$prevToken]['code'] === \T_STATIC); + } + + + /** + * Check if the code within a closure uses the $this variable. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $startToken The position within the closure to continue searching from. + * @param int $endToken The closure scope closer to stop searching at. + * + * @return int|false The stackPtr to the first $this usage if found or false if + * $this is not used. + */ + protected function findThisUsageInClosure(File $phpcsFile, $startToken, $endToken) + { + // Make sure the $startToken is valid. + if ($startToken >= $endToken) { + return false; + } + + return $phpcsFile->findNext( + \T_VARIABLE, + $startToken, + $endToken, + false, + '$this' + ); + } + + /** + * Check if the code within a closure uses "self/parent/static". + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $startToken The position within the closure to continue searching from. + * @param int $endToken The closure scope closer to stop searching at. + * + * @return int|false The stackPtr to the first classRef usage if found or false if + * they are not used. + */ + protected function findClassRefUsageInClosure(File $phpcsFile, $startToken, $endToken) + { + // Make sure the $startToken is valid. + if ($startToken >= $endToken) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + $classRef = $phpcsFile->findNext(array(\T_SELF, \T_PARENT, \T_STATIC), $startToken, $endToken); + + if ($classRef === false || $tokens[$classRef]['code'] !== \T_STATIC) { + return $classRef; + } + + // T_STATIC, make sure it is used as a class reference. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($classRef + 1), $endToken, true); + if ($next === false || $tokens[$next]['code'] !== \T_DOUBLE_COLON) { + return false; + } + + return $classRef; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php new file mode 100644 index 000000000..056489615 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewExceptionsFromToStringSniff.php @@ -0,0 +1,171 @@ + true, + 'T_TRAIT' => true, + 'T_ANON_CLASS' => true, + ); + + /** + * Tokens which should be ignored when they preface a function declaration + * when trying to find the docblock (if any). + * + * Array will be added to in the register() method. + * + * @since 9.3.0 + * + * @var array + */ + private $docblockIgnoreTokens = array( + \T_WHITESPACE => \T_WHITESPACE, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + // Enhance the array of tokens to ignore for finding the docblock. + $this->docblockIgnoreTokens += Tokens::$methodPrefixes; + if (isset(Tokens::$phpcsCommentTokens)) { + $this->docblockIgnoreTokens += Tokens::$phpcsCommentTokens; + } + + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + // Abstract function, interface function, live coding or parse error. + return; + } + + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if (strtolower($functionName) !== '__tostring') { + // Not the right function. + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) === false) { + // Function, not method. + return; + } + + /* + * Examine the content of the function. + */ + $error = 'Throwing exceptions from __toString() was not allowed prior to PHP 7.4'; + $throwPtr = $tokens[$stackPtr]['scope_opener']; + $errorThrown = false; + + do { + $throwPtr = $phpcsFile->findNext(\T_THROW, ($throwPtr + 1), $tokens[$stackPtr]['scope_closer']); + if ($throwPtr === false) { + break; + } + + $conditions = $tokens[$throwPtr]['conditions']; + $conditions = array_reverse($conditions, true); + $inTryCatch = false; + foreach ($conditions as $ptr => $type) { + if ($type === \T_TRY) { + $inTryCatch = true; + break; + } + + if ($ptr === $stackPtr) { + // Don't check the conditions outside the function scope. + break; + } + } + + if ($inTryCatch === false) { + $phpcsFile->addError($error, $throwPtr, 'Found'); + $errorThrown = true; + } + } while (true); + + if ($errorThrown === true) { + // We've already thrown an error for this method, no need to examine the docblock. + return; + } + + /* + * Check whether the function has a docblock and if so, whether it contains a @throws tag. + * + * {@internal This can be partially replaced by the findCommentAboveFunction() + * utility function in due time.} + */ + $commentEnd = $phpcsFile->findPrevious($this->docblockIgnoreTokens, ($stackPtr - 1), null, true); + if ($commentEnd === false || $tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + // Found a throws tag. + $phpcsFile->addError($error, $stackPtr, 'ThrowsTagFoundInDocblock'); + break; + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php new file mode 100644 index 000000000..8dc0c4160 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewNullableTypesSniff.php @@ -0,0 +1,169 @@ +supportsBelow('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + + if ($tokenCode === \T_FUNCTION || $tokenCode === \T_CLOSURE) { + $this->processFunctionDeclaration($phpcsFile, $stackPtr); + + // Deal with older PHPCS version which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $this->processReturnType($phpcsFile, $returnTypeHint); + } + } else { + $this->processReturnType($phpcsFile, $stackPtr); + } + } + + + /** + * Process this test for function tokens. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processFunctionDeclaration(File $phpcsFile, $stackPtr) + { + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + + if (empty($params) === false && \is_array($params)) { + foreach ($params as $param) { + if ($param['nullable_type'] === true) { + $phpcsFile->addError( + 'Nullable type declarations are not supported in PHP 7.0 or earlier. Found: %s', + $param['token'], + 'typeDeclarationFound', + array($param['type_hint']) + ); + } + } + } + } + + + /** + * Process this test for return type tokens. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processReturnType(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr - 1)]['code']) === false) { + return; + } + + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Deal with namespaced class names. + if ($tokens[$previous]['code'] === \T_NS_SEPARATOR) { + $validTokens = Tokens::$emptyTokens; + $validTokens[\T_STRING] = true; + $validTokens[\T_NS_SEPARATOR] = true; + + $stackPtr--; + + while (isset($validTokens[$tokens[($stackPtr - 1)]['code']]) === true) { + $stackPtr--; + } + + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + } + + // T_NULLABLE token was introduced in PHPCS 2.7.2. Before that it identified as T_INLINE_THEN. + if ((\defined('T_NULLABLE') === true && $tokens[$previous]['type'] === 'T_NULLABLE') + || (\defined('T_NULLABLE') === false && $tokens[$previous]['code'] === \T_INLINE_THEN) + ) { + $phpcsFile->addError( + 'Nullable return types are not supported in PHP 7.0 or earlier.', + $stackPtr, + 'returnTypeFound' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php new file mode 100644 index 000000000..6ad98b6a7 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewParamTypeDeclarationsSniff.php @@ -0,0 +1,237 @@ + array(string => bool)) + */ + protected $newTypes = array( + 'array' => array( + '5.0' => false, + '5.1' => true, + ), + 'self' => array( + '5.1' => false, + '5.2' => true, + ), + 'parent' => array( + '5.1' => false, + '5.2' => true, + ), + 'callable' => array( + '5.3' => false, + '5.4' => true, + ), + 'int' => array( + '5.6' => false, + '7.0' => true, + ), + 'float' => array( + '5.6' => false, + '7.0' => true, + ), + 'bool' => array( + '5.6' => false, + '7.0' => true, + ), + 'string' => array( + '5.6' => false, + '7.0' => true, + ), + 'iterable' => array( + '7.0' => false, + '7.1' => true, + ), + 'object' => array( + '7.1' => false, + '7.2' => true, + ), + ); + + + /** + * Invalid types + * + * The array lists : the invalid type hint => what was probably intended/alternative. + * + * @since 7.0.3 + * + * @var array(string => string) + */ + protected $invalidTypes = array( + 'static' => 'self', + 'boolean' => 'bool', + 'integer' => 'int', + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 7.1.3 Now also checks closures. + * + * @return array + */ + public function register() + { + return array( + \T_FUNCTION, + \T_CLOSURE, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * @since 7.0.3 - Added check for non-scalar type declarations. + * - Added check for invalid type declarations. + * - Added check for usage of `self` type declaration outside + * class scope. + * @since 8.2.0 Added check for `parent` type declaration outside class scope. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Get all parameters from method signature. + $paramNames = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($paramNames)) { + return; + } + + $supportsPHP4 = $this->supportsBelow('4.4'); + + foreach ($paramNames as $param) { + if ($param['type_hint'] === '') { + continue; + } + + // Strip off potential nullable indication. + $typeHint = ltrim($param['type_hint'], '?'); + + if ($supportsPHP4 === true) { + $phpcsFile->addError( + 'Type declarations were not present in PHP 4.4 or earlier.', + $param['token'], + 'TypeHintFound' + ); + + } elseif (isset($this->newTypes[$typeHint])) { + $itemInfo = array( + 'name' => $typeHint, + ); + $this->handleFeature($phpcsFile, $param['token'], $itemInfo); + + // As of PHP 7.0, using `self` or `parent` outside class scope throws a fatal error. + // Only throw this error for PHP 5.2+ as before that the "type hint not supported" error + // will be thrown. + if (($typeHint === 'self' || $typeHint === 'parent') + && $this->inClassScope($phpcsFile, $stackPtr, false) === false + && $this->supportsAbove('5.2') !== false + ) { + $phpcsFile->addError( + "'%s' type cannot be used outside of class scope", + $param['token'], + ucfirst($typeHint) . 'OutsideClassScopeFound', + array($typeHint) + ); + } + } elseif (isset($this->invalidTypes[$typeHint])) { + $error = "'%s' is not a valid type declaration. Did you mean %s ?"; + $data = array( + $typeHint, + $this->invalidTypes[$typeHint], + ); + + $phpcsFile->addError($error, $param['token'], 'InvalidTypeHintFound', $data); + } + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newTypes[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "'%s' type declaration is not present in PHP version %s or earlier"; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php new file mode 100644 index 000000000..3e225616e --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NewReturnTypeDeclarationsSniff.php @@ -0,0 +1,194 @@ + array(string => bool)) + */ + protected $newTypes = array( + 'int' => array( + '5.6' => false, + '7.0' => true, + ), + 'float' => array( + '5.6' => false, + '7.0' => true, + ), + 'bool' => array( + '5.6' => false, + '7.0' => true, + ), + 'string' => array( + '5.6' => false, + '7.0' => true, + ), + 'array' => array( + '5.6' => false, + '7.0' => true, + ), + 'callable' => array( + '5.6' => false, + '7.0' => true, + ), + 'parent' => array( + '5.6' => false, + '7.0' => true, + ), + 'self' => array( + '5.6' => false, + '7.0' => true, + ), + 'Class name' => array( + '5.6' => false, + '7.0' => true, + ), + + 'iterable' => array( + '7.0' => false, + '7.1' => true, + ), + 'void' => array( + '7.0' => false, + '7.1' => true, + ), + + 'object' => array( + '7.1' => false, + '7.2' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 7.1.2 Now also checks based on the function and closure keywords. + * + * @return array + */ + public function register() + { + $tokens = array( + \T_FUNCTION, + \T_CLOSURE, + ); + + if (\defined('T_RETURN_TYPE')) { + $tokens[] = \T_RETURN_TYPE; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Deal with older PHPCS version which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + if ($tokens[$stackPtr]['code'] === \T_FUNCTION || $tokens[$stackPtr]['code'] === \T_CLOSURE) { + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $stackPtr = $returnTypeHint; + } + } + + if (isset($this->newTypes[$tokens[$stackPtr]['content']]) === true) { + $itemInfo = array( + 'name' => $tokens[$stackPtr]['content'], + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + // Handle class name based return types. + elseif ($tokens[$stackPtr]['code'] === \T_STRING + || (\defined('T_RETURN_TYPE') && $tokens[$stackPtr]['code'] === \T_RETURN_TYPE) + ) { + $itemInfo = array( + 'name' => 'Class name', + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newTypes[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return '%s return type is not present in PHP version %s or earlier'; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php new file mode 100644 index 000000000..a86d56ef1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionDeclarations/NonStaticMagicMethodsSniff.php @@ -0,0 +1,216 @@ + array( + 'static' => false, + ), + '__destruct' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__clone' => array( + 'static' => false, + ), + '__get' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__set' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__isset' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__unset' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__call' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__callstatic' => array( + 'visibility' => 'public', + 'static' => true, + ), + '__sleep' => array( + 'visibility' => 'public', + ), + '__tostring' => array( + 'visibility' => 'public', + ), + '__set_state' => array( + 'visibility' => 'public', + 'static' => true, + ), + '__debuginfo' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__invoke' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__serialize' => array( + 'visibility' => 'public', + 'static' => false, + ), + '__unserialize' => array( + 'visibility' => 'public', + 'static' => false, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * @since 5.6 Now also checks traits. + * @since 7.1.4 Now also checks anonymous classes. + * + * @return array + */ + public function register() + { + $targets = array( + \T_CLASS, + \T_INTERFACE, + \T_TRAIT, + ); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Should be removed, the requirement was previously also there, 5.3 just started throwing a warning about it. + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $classScopeCloser = $tokens[$stackPtr]['scope_closer']; + $functionPtr = $stackPtr; + + // Find all the functions in this class or interface. + while (($functionToken = $phpcsFile->findNext(\T_FUNCTION, $functionPtr, $classScopeCloser)) !== false) { + /* + * Get the scope closer for this function in order to know how + * to advance to the next function. + * If no body of function (e.g. for interfaces), there is + * no closing curly brace; advance the pointer differently. + */ + if (isset($tokens[$functionToken]['scope_closer'])) { + $scopeCloser = $tokens[$functionToken]['scope_closer']; + } else { + $scopeCloser = ($functionToken + 1); + } + + $methodName = $phpcsFile->getDeclarationName($functionToken); + $methodNameLc = strtolower($methodName); + if (isset($this->magicMethods[$methodNameLc]) === false) { + $functionPtr = $scopeCloser; + continue; + } + + $methodProperties = $phpcsFile->getMethodProperties($functionToken); + $errorCodeBase = $this->stringToErrorCode($methodNameLc); + + if (isset($this->magicMethods[$methodNameLc]['visibility']) && $this->magicMethods[$methodNameLc]['visibility'] !== $methodProperties['scope']) { + $error = 'Visibility for magic method %s must be %s. Found: %s'; + $errorCode = $errorCodeBase . 'MethodVisibility'; + $data = array( + $methodName, + $this->magicMethods[$methodNameLc]['visibility'], + $methodProperties['scope'], + ); + + $phpcsFile->addError($error, $functionToken, $errorCode, $data); + } + + if (isset($this->magicMethods[$methodNameLc]['static']) && $this->magicMethods[$methodNameLc]['static'] !== $methodProperties['is_static']) { + $error = 'Magic method %s cannot be defined as static.'; + $errorCode = $errorCodeBase . 'MethodStatic'; + $data = array($methodName); + + if ($this->magicMethods[$methodNameLc]['static'] === true) { + $error = 'Magic method %s must be defined as static.'; + $errorCode = $errorCodeBase . 'MethodNonStatic'; + } + + $phpcsFile->addError($error, $functionToken, $errorCode, $data); + } + + // Advance to next function. + $functionPtr = $scopeCloser; + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php new file mode 100644 index 000000000..4dc08f880 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/NewMagicMethodsSniff.php @@ -0,0 +1,231 @@ + array(string => bool|string)) + */ + protected $newMagicMethods = array( + '__construct' => array( + '4.4' => false, + '5.0' => true, + ), + '__destruct' => array( + '4.4' => false, + '5.0' => true, + ), + '__get' => array( + '4.4' => false, + '5.0' => true, + ), + + '__isset' => array( + '5.0' => false, + '5.1' => true, + ), + '__unset' => array( + '5.0' => false, + '5.1' => true, + ), + '__set_state' => array( + '5.0' => false, + '5.1' => true, + ), + + '__callstatic' => array( + '5.2' => false, + '5.3' => true, + ), + '__invoke' => array( + '5.2' => false, + '5.3' => true, + ), + + '__debuginfo' => array( + '5.5' => false, + '5.6' => true, + ), + + // Special case - only became properly magical in 5.2.0, + // before that it was only called for echo and print. + '__tostring' => array( + '5.1' => false, + '5.2' => true, + 'message' => 'The method %s() was not truly magical in PHP version %s and earlier. The associated magic functionality will only be called when directly combined with echo or print.', + ), + + '__serialize' => array( + '7.3' => false, + '7.4' => true, + ), + '__unserialize' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.4 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + $functionNameLc = strtolower($functionName); + + if (isset($this->newMagicMethods[$functionNameLc]) === false) { + return; + } + + if ($this->inClassScope($phpcsFile, $stackPtr, false) === false) { + return; + } + + $itemInfo = array( + 'name' => $functionName, + 'nameLc' => $functionNameLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newMagicMethods[$itemInfo['nameLc']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('message'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['error'] = false; // Warning, not error. + $errorInfo['message'] = ''; + + if (empty($itemArray['message']) === false) { + $errorInfo['message'] = $itemArray['message']; + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The method %s() was not magical in PHP version %s and earlier. The associated magic functionality will not be invoked.'; + } + + + /** + * Allow for concrete child classes to filter the error message before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + if ($errorInfo['message'] !== '') { + $error = $errorInfo['message']; + } + + return $error; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php new file mode 100644 index 000000000..0ea5b0d62 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedMagicAutoloadSniff.php @@ -0,0 +1,92 @@ + true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_NAMESPACE' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.1.0 + * + * @return array + */ + public function register() + { + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.2') === false) { + return; + } + + $funcName = $phpcsFile->getDeclarationName($stackPtr); + + if (strtolower($funcName) !== '__autoload') { + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->checkForScopes) !== false) { + return; + } + + if ($this->determineNamespace($phpcsFile, $stackPtr) !== '') { + return; + } + + $phpcsFile->addWarning('Use of __autoload() function is deprecated since PHP 7.2', $stackPtr, 'Found'); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php new file mode 100644 index 000000000..3c3feadc2 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedNamespacedAssertSniff.php @@ -0,0 +1,101 @@ +scopes[] = \T_ANON_CLASS; + } + + return array(\T_FUNCTION); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.3') === false) { + return; + } + + $funcName = $phpcsFile->getDeclarationName($stackPtr); + + if (strtolower($funcName) !== 'assert') { + return; + } + + if ($phpcsFile->hasCondition($stackPtr, $this->scopes) === true) { + return; + } + + if ($this->determineNamespace($phpcsFile, $stackPtr) === '') { + // Not a namespaced function declaration. This may be a parse error, but not our concern. + return; + } + + $phpcsFile->addWarning('Declaring a free-standing function called assert() is deprecated since PHP 7.3.', $stackPtr, 'Found'); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php new file mode 100644 index 000000000..a888f51d8 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/RemovedPHP4StyleConstructorsSniff.php @@ -0,0 +1,158 @@ +supportsAbove('7.0') === false) { + return; + } + + if ($this->determineNamespace($phpcsFile, $stackPtr) !== '') { + /* + * Namespaced methods with the same name as the class are treated as + * regular methods, so we can bow out if we're in a namespace. + * + * Note: the exception to this is PHP 5.3.0-5.3.2. This is currently + * not dealt with. + */ + return; + } + + $tokens = $phpcsFile->getTokens(); + + $class = $tokens[$stackPtr]; + + if (isset($class['scope_closer']) === false) { + return; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + // Anonymous class in combination with PHPCS 2.3.x. + return; + } + + $scopeCloser = $class['scope_closer']; + $className = $tokens[$nextNonEmpty]['content']; + + if (empty($className) || \is_string($className) === false) { + return; + } + + $nextFunc = $stackPtr; + $classNameLc = strtolower($className); + $newConstructorFound = false; + $oldConstructorFound = false; + $oldConstructorPos = -1; + while (($nextFunc = $phpcsFile->findNext(array(\T_FUNCTION, \T_DOC_COMMENT_OPEN_TAG), ($nextFunc + 1), $scopeCloser)) !== false) { + // Skip over docblocks. + if ($tokens[$nextFunc]['code'] === \T_DOC_COMMENT_OPEN_TAG) { + $nextFunc = $tokens[$nextFunc]['comment_closer']; + continue; + } + + $functionScopeCloser = $nextFunc; + if (isset($tokens[$nextFunc]['scope_closer'])) { + // Normal (non-interface, non-abstract) method. + $functionScopeCloser = $tokens[$nextFunc]['scope_closer']; + } + + $funcName = $phpcsFile->getDeclarationName($nextFunc); + if (empty($funcName) || \is_string($funcName) === false) { + $nextFunc = $functionScopeCloser; + continue; + } + + $funcNameLc = strtolower($funcName); + + if ($funcNameLc === '__construct') { + $newConstructorFound = true; + } + + if ($funcNameLc === $classNameLc) { + $oldConstructorFound = true; + $oldConstructorPos = $nextFunc; + } + + // If both have been found, no need to continue looping through the functions. + if ($newConstructorFound === true && $oldConstructorFound === true) { + break; + } + + $nextFunc = $functionScopeCloser; + } + + if ($newConstructorFound === false && $oldConstructorFound === true) { + $phpcsFile->addWarning( + 'Use of deprecated PHP4 style class constructor is not supported since PHP 7.', + $oldConstructorPos, + 'Found' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php new file mode 100644 index 000000000..9ddb9e96c --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionNameRestrictions/ReservedFunctionNamesSniff.php @@ -0,0 +1,205 @@ +magicMethods['debuginfo'] = true; + } + + + /** + * Processes the tokens within the scope. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + /* + * Determine if this is a function which needs to be examined. + * The `processTokenWithinScope()` is called for each valid scope a method is in, + * so for nested classes, we need to make sure we only examine the token for + * the lowest level valid scope. + */ + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + if ($this->isFunctionDeprecated($phpcsFile, $stackPtr) === true) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) > 0) { + $magicPart = strtolower(substr($methodName, 2)); + if (isset($this->magicMethods[$magicPart]) === false + && isset($this->methodsDoubleUnderscore[$magicPart]) === false + ) { + $className = '[anonymous class]'; + $scopeNextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($currScope + 1), null, true); + if ($scopeNextNonEmpty !== false && $tokens[$scopeNextNonEmpty]['code'] === \T_STRING) { + $className = $tokens[$scopeNextNonEmpty]['content']; + } + + $phpcsFile->addWarning( + 'Method name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.', + $stackPtr, + 'MethodDoubleUnderscore', + array($className . '::' . $methodName) + ); + } + } + } + + + /** + * Processes the tokens outside the scope. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + if ($this->isFunctionDeprecated($phpcsFile, $stackPtr) === true) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) > 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === false) { + $phpcsFile->addWarning( + 'Function name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.', + $stackPtr, + 'FunctionDoubleUnderscore', + array($functionName) + ); + } + } + } + + + /** + * Check whether a function has been marked as deprecated via a @deprecated tag + * in the function docblock. + * + * @since 9.3.2 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_FUNCTION + * token in the stack. + * + * @return bool + */ + private function isFunctionDeprecated(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = \T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== \T_DOC_COMMENT_CLOSE_TAG) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return false; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@deprecated') { + return true; + } + } + + return false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php new file mode 100644 index 000000000..4e904dea3 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsReportCurrentValueSniff.php @@ -0,0 +1,455 @@ + true, + 'func_get_args' => true, + 'debug_backtrace' => true, + 'debug_print_backtrace' => true, + ); + + /** + * Tokens to look out for to allow us to skip past nested scoped structures. + * + * @since 9.1.0 + * + * @var array + */ + private $skipPastNested = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + ); + + /** + * List of tokens which when they preceed a T_STRING *within a function* indicate + * this is not a call to a PHP native function. + * + * This list already takes into account that nested scoped structures are being + * skipped over, so doesn't check for those again. + * Similarly, as constants won't have parentheses, those don't need to be checked + * for either. + * + * @since 9.1.0 + * + * @var array + */ + private $noneFunctionCallIndicators = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + ); + + /** + * The tokens for variable incrementing/decrementing. + * + * @since 9.1.0 + * + * @var array + */ + private $plusPlusMinusMinus = array( + \T_DEC => true, + \T_INC => true, + ); + + /** + * Tokens to ignore when determining the start of a statement. + * + * @since 9.1.0 + * + * @var array + */ + private $ignoreForStartOfStatement = array( + \T_COMMA, + \T_DOUBLE_ARROW, + \T_OPEN_SQUARE_BRACKET, + \T_OPEN_PARENTHESIS, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.1.0 + * + * @return array + */ + public function register() + { + return array( + \T_FUNCTION, + \T_CLOSURE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + // Abstract function, interface function, live coding or parse error. + return; + } + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + // Does the function declaration have parameters ? + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + // No named arguments found, so no risk of them being changed. + return; + } + + $paramNames = array(); + foreach ($params as $param) { + $paramNames[] = $param['name']; + } + + for ($i = ($scopeOpener + 1); $i < $scopeCloser; $i++) { + if (isset($this->skipPastNested[$tokens[$i]['type']]) && isset($tokens[$i]['scope_closer'])) { + // Skip past nested structures. + $i = $tokens[$i]['scope_closer']; + continue; + } + + if ($tokens[$i]['code'] !== \T_STRING) { + continue; + } + + $foundFunctionName = strtolower($tokens[$i]['content']); + + if (isset($this->changedFunctions[$foundFunctionName]) === false) { + // Not one of the target functions. + continue; + } + + /* + * Ok, so is this really a function call to one of the PHP native functions ? + */ + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== \T_OPEN_PARENTHESIS) { + // Live coding, parse error or not a function call. + continue; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($prev !== false) { + if (isset($this->noneFunctionCallIndicators[$tokens[$prev]['code']])) { + continue; + } + + // Check for namespaced functions, ie: \foo\bar() not \bar(). + if ($tokens[ $prev ]['code'] === \T_NS_SEPARATOR) { + $pprev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($pprev !== false && $tokens[ $pprev ]['code'] === \T_STRING) { + continue; + } + } + } + + /* + * Address some special cases. + */ + if ($foundFunctionName !== 'func_get_args') { + $paramOne = $this->getFunctionCallParameter($phpcsFile, $i, 1); + if ($paramOne !== false) { + switch ($foundFunctionName) { + /* + * Check if `debug_(print_)backtrace()` is called with the + * `DEBUG_BACKTRACE_IGNORE_ARGS` option. + */ + case 'debug_backtrace': + case 'debug_print_backtrace': + $hasIgnoreArgs = $phpcsFile->findNext( + \T_STRING, + $paramOne['start'], + ($paramOne['end'] + 1), + false, + 'DEBUG_BACKTRACE_IGNORE_ARGS' + ); + + if ($hasIgnoreArgs !== false) { + // Debug_backtrace() called with ignore args option. + continue 2; + } + break; + + /* + * Collect the necessary information to only throw a notice if the argument + * touched/changed is in line with the passed $arg_num. + * + * Also, we can ignore `func_get_arg()` if the argument offset passed is + * higher than the number of named parameters. + * + * {@internal Note: This does not take calculations into account! + * Should be exceptionally rare and can - if needs be - be addressed at a later stage.} + */ + case 'func_get_arg': + $number = $phpcsFile->findNext(\T_LNUMBER, $paramOne['start'], ($paramOne['end'] + 1)); + if ($number !== false) { + $argNumber = $tokens[$number]['content']; + + if (isset($paramNames[$argNumber]) === false) { + // Requesting a non-named additional parameter. Ignore. + continue 2; + } + } + break; + } + } + } else { + /* + * Check if the call to func_get_args() happens to be in an array_slice() or + * array_splice() with an $offset higher than the number of named parameters. + * In that case, we can ignore it. + * + * {@internal Note: This does not take offset calculations into account! + * Should be exceptionally rare and can - if needs be - be addressed at a later stage.} + */ + if ($prev !== false && $tokens[$prev]['code'] === \T_OPEN_PARENTHESIS) { + + $maybeFunctionCall = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($maybeFunctionCall !== false + && $tokens[$maybeFunctionCall]['code'] === \T_STRING + && ($tokens[$maybeFunctionCall]['content'] === 'array_slice' + || $tokens[$maybeFunctionCall]['content'] === 'array_splice') + ) { + $parentFuncParamTwo = $this->getFunctionCallParameter($phpcsFile, $maybeFunctionCall, 2); + $number = $phpcsFile->findNext( + \T_LNUMBER, + $parentFuncParamTwo['start'], + ($parentFuncParamTwo['end'] + 1) + ); + + if ($number !== false && isset($paramNames[$tokens[$number]['content']]) === false) { + // Requesting non-named additional parameters. Ignore. + continue ; + } + + // Slice starts at a named argument, but we know which params are being accessed. + $paramNamesSubset = \array_slice($paramNames, $tokens[$number]['content']); + } + } + } + + /* + * For debug_backtrace(), check if the result is being dereferenced and if so, + * whether the `args` index is used. + * I.e. whether `$index` in `debug_backtrace()[$stackFrame][$index]` is a string + * with the content `args`. + * + * Note: We already know that $next is the open parenthesis of the function call. + */ + if ($foundFunctionName === 'debug_backtrace' && isset($tokens[$next]['parenthesis_closer'])) { + $afterParenthesis = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($tokens[$next]['parenthesis_closer'] + 1), + null, + true + ); + + if ($tokens[$afterParenthesis]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$afterParenthesis]['bracket_closer']) + ) { + $afterStackFrame = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($tokens[$afterParenthesis]['bracket_closer'] + 1), + null, + true + ); + + if ($tokens[$afterStackFrame]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$afterStackFrame]['bracket_closer']) + ) { + $arrayIndex = $phpcsFile->findNext( + \T_CONSTANT_ENCAPSED_STRING, + ($afterStackFrame + 1), + $tokens[$afterStackFrame]['bracket_closer'] + ); + + if ($arrayIndex !== false && $this->stripQuotes($tokens[$arrayIndex]['content']) !== 'args') { + continue; + } + } + } + } + + /* + * Only check for variables before the start of the statement to + * prevent false positives on the return value of the function call + * being assigned to one of the parameters, i.e.: + * `$param = func_get_args();`. + */ + $startOfStatement = PHPCSHelper::findStartOfStatement($phpcsFile, $i, $this->ignoreForStartOfStatement); + + /* + * Ok, so we've found one of the target functions in the right scope. + * Now, let's check if any of the passed parameters were touched. + */ + $scanResult = 'clean'; + for ($j = ($scopeOpener + 1); $j < $startOfStatement; $j++) { + if (isset($this->skipPastNested[$tokens[$j]['type']]) + && isset($tokens[$j]['scope_closer']) + ) { + // Skip past nested structures. + $j = $tokens[$j]['scope_closer']; + continue; + } + + if ($tokens[$j]['code'] !== \T_VARIABLE) { + continue; + } + + if ($foundFunctionName === 'func_get_arg' && isset($argNumber)) { + if (isset($paramNames[$argNumber]) + && $tokens[$j]['content'] !== $paramNames[$argNumber] + ) { + // Different param than the one requested by func_get_arg(). + continue; + } + } elseif ($foundFunctionName === 'func_get_args' && isset($paramNamesSubset)) { + if (\in_array($tokens[$j]['content'], $paramNamesSubset, true) === false) { + // Different param than the ones requested by func_get_args(). + continue; + } + } elseif (\in_array($tokens[$j]['content'], $paramNames, true) === false) { + // Variable is not one of the function parameters. + continue; + } + + /* + * Ok, so we've found a variable which was passed as one of the parameters. + * Now, is this variable being changed, i.e. incremented, decremented or + * assigned something ? + */ + $scanResult = 'warning'; + if (isset($variableToken) === false) { + $variableToken = $j; + } + + $beforeVar = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($j - 1), null, true); + if ($beforeVar !== false && isset($this->plusPlusMinusMinus[$tokens[$beforeVar]['code']])) { + // Variable is being (pre-)incremented/decremented. + $scanResult = 'error'; + $variableToken = $j; + break; + } + + $afterVar = $phpcsFile->findNext(Tokens::$emptyTokens, ($j + 1), null, true); + if ($afterVar === false) { + // Shouldn't be possible, but just in case. + continue; + } + + if (isset($this->plusPlusMinusMinus[$tokens[$afterVar]['code']])) { + // Variable is being (post-)incremented/decremented. + $scanResult = 'error'; + $variableToken = $j; + break; + } + + if ($tokens[$afterVar]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$afterVar]['bracket_closer']) + ) { + // Skip past array access on the variable. + while (($afterVar = $phpcsFile->findNext(Tokens::$emptyTokens, ($tokens[$afterVar]['bracket_closer'] + 1), null, true)) !== false) { + if ($tokens[$afterVar]['code'] !== \T_OPEN_SQUARE_BRACKET + || isset($tokens[$afterVar]['bracket_closer']) === false + ) { + break; + } + } + } + + if ($afterVar !== false + && isset(Tokens::$assignmentTokens[$tokens[$afterVar]['code']]) + ) { + // Variable is being assigned something. + $scanResult = 'error'; + $variableToken = $j; + break; + } + } + + unset($argNumber, $paramNamesSubset); + + if ($scanResult === 'clean') { + continue; + } + + $error = 'Since PHP 7.0, functions inspecting arguments, like %1$s(), no longer report the original value as passed to a parameter, but will instead provide the current value. The parameter "%2$s" was %4$s on line %3$s.'; + $data = array( + $foundFunctionName, + $tokens[$variableToken]['content'], + $tokens[$variableToken]['line'], + ); + + if ($scanResult === 'error') { + $data[] = 'changed'; + $phpcsFile->addError($error, $i, 'Changed', $data); + + } elseif ($scanResult === 'warning') { + $data[] = 'used, and possibly changed (by reference),'; + $phpcsFile->addWarning($error, $i, 'NeedsInspection', $data); + } + + unset($variableToken); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php new file mode 100644 index 000000000..7c2511196 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/ArgumentFunctionsUsageSniff.php @@ -0,0 +1,169 @@ + true, + 'func_get_arg' => true, + 'func_num_args' => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $functionLc = strtolower($tokens[$stackPtr]['content']); + if (isset($this->targetFunctions[$functionLc]) === false) { + return; + } + + // Next non-empty token should be the open parenthesis. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + return; + } + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_NEW => true, + ); + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevNonEmpty]['code']]) === true) { + // Not a call to a PHP function. + return; + } elseif ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING) { + // Namespaced function. + return; + } + + $data = $tokens[$stackPtr]['content']; + + /* + * Check for use of the functions in the global scope. + * + * As PHPCS can not determine whether a file is included from within a function in + * another file, so always throw a warning/error. + */ + if ($phpcsFile->hasCondition($stackPtr, array(\T_FUNCTION, \T_CLOSURE)) === false) { + $isError = false; + $message = 'Use of %s() outside of a user-defined function is only supported if the file is included from within a user-defined function in another file prior to PHP 5.3.'; + + if ($this->supportsAbove('5.3') === true) { + $isError = true; + $message .= ' As of PHP 5.3, it is no longer supported at all.'; + } + + $this->addMessage($phpcsFile, $message, $stackPtr, $isError, 'OutsideFunctionScope', $data); + } + + /* + * Check for use of the functions as a parameter in a function call. + */ + if ($this->supportsBelow('5.2') === false) { + return; + } + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === false) { + return; + } + + $throwError = false; + + $closer = end($tokens[$stackPtr]['nested_parenthesis']); + if (isset($tokens[$closer]['parenthesis_owner']) + && $tokens[$tokens[$closer]['parenthesis_owner']]['type'] === 'T_CLOSURE' + ) { + $throwError = true; + } else { + $opener = key($tokens[$stackPtr]['nested_parenthesis']); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true); + if ($tokens[$prevNonEmpty]['code'] !== \T_STRING) { + return; + } + + $prevPrevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true); + if ($tokens[$prevPrevNonEmpty]['code'] === \T_FUNCTION) { + return; + } + + $throwError = true; + } + + if ($throwError === false) { + return; + } + + $phpcsFile->addError( + '%s() could not be used in parameter lists prior to PHP 5.3.', + $stackPtr, + 'InParameterList', + $data + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php new file mode 100644 index 000000000..7b0d60bd7 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionParametersSniff.php @@ -0,0 +1,1109 @@ + array( + 2 => array( + 'name' => 'flag', + '5.5' => false, + '5.6' => true, + ), + ), + 'array_slice' => array( + 1 => array( + 'name' => 'preserve_keys', + '5.0.1' => false, + '5.0.2' => true, + ), + ), + 'array_unique' => array( + 1 => array( + 'name' => 'sort_flags', + '5.2.8' => false, + '5.2.9' => true, + ), + ), + 'assert' => array( + 1 => array( + 'name' => 'description', + '5.4.7' => false, + '5.4.8' => true, + ), + ), + 'base64_decode' => array( + 1 => array( + 'name' => 'strict', + '5.1' => false, + '5.2' => true, + ), + ), + 'bcmod' => array( + 2 => array( + 'name' => 'scale', + '7.1' => false, + '7.2' => true, + ), + ), + 'class_implements' => array( + 1 => array( + 'name' => 'autoload', + '5.0' => false, + '5.1' => true, + ), + ), + 'class_parents' => array( + 1 => array( + 'name' => 'autoload', + '5.0' => false, + '5.1' => true, + ), + ), + 'clearstatcache' => array( + 0 => array( + 'name' => 'clear_realpath_cache', + '5.2' => false, + '5.3' => true, + ), + 1 => array( + 'name' => 'filename', + '5.2' => false, + '5.3' => true, + ), + ), + 'copy' => array( + 2 => array( + 'name' => 'context', + '5.2' => false, + '5.3' => true, + ), + ), + 'curl_multi_info_read' => array( + 1 => array( + 'name' => 'msgs_in_queue', + '5.1' => false, + '5.2' => true, + ), + ), + 'debug_backtrace' => array( + 0 => array( + 'name' => 'options', + '5.2.4' => false, + '5.2.5' => true, + ), + 1 => array( + 'name' => 'limit', + '5.3' => false, + '5.4' => true, + ), + ), + 'debug_print_backtrace' => array( + 0 => array( + 'name' => 'options', + '5.3.5' => false, + '5.3.6' => true, + ), + 1 => array( + 'name' => 'limit', + '5.3' => false, + '5.4' => true, + ), + ), + 'dirname' => array( + 1 => array( + 'name' => 'levels', + '5.6' => false, + '7.0' => true, + ), + ), + 'dns_get_record' => array( + 4 => array( + 'name' => 'raw', + '5.3' => false, + '5.4' => true, + ), + ), + 'fgetcsv' => array( + 4 => array( + 'name' => 'escape', + '5.2' => false, + '5.3' => true, + ), + ), + 'fputcsv' => array( + 4 => array( + 'name' => 'escape_char', + '5.5.3' => false, + '5.5.4' => true, + ), + ), + 'file_get_contents' => array( + 3 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + 4 => array( + 'name' => 'maxlen', + '5.0' => false, + '5.1' => true, + ), + ), + 'filter_input_array' => array( + 2 => array( + 'name' => 'add_empty', + '5.3' => false, + '5.4' => true, + ), + ), + 'filter_var_array' => array( + 2 => array( + 'name' => 'add_empty', + '5.3' => false, + '5.4' => true, + ), + ), + 'getenv' => array( + 1 => array( + 'name' => 'local_only', + '5.5.37' => false, + '5.5.38' => true, // Also introduced in PHP 5.6.24 and 7.0.9. + ), + ), + 'getopt' => array( + 2 => array( + 'name' => 'optind', + '7.0' => false, + '7.1' => true, + ), + ), + 'gettimeofday' => array( + 0 => array( + 'name' => 'return_float', + '5.0' => false, + '5.1' => true, + ), + ), + 'get_defined_functions' => array( + 0 => array( + 'name' => 'exclude_disabled', + '7.0.14' => false, + '7.0.15' => true, + ), + ), + 'get_headers' => array( + 2 => array( + 'name' => 'context', + '7.0' => false, + '7.1' => true, + ), + ), + 'get_html_translation_table' => array( + 2 => array( + 'name' => 'encoding', + '5.3.3' => false, + '5.3.4' => true, + ), + ), + 'get_loaded_extensions' => array( + 0 => array( + 'name' => 'zend_extensions', + '5.2.3' => false, + '5.2.4' => true, + ), + ), + 'gzcompress' => array( + 2 => array( + 'name' => 'encoding', + '5.3' => false, + '5.4' => true, + ), + ), + 'gzdeflate' => array( + 2 => array( + 'name' => 'encoding', + '5.3' => false, + '5.4' => true, + ), + ), + 'htmlentities' => array( + 3 => array( + 'name' => 'double_encode', + '5.2.2' => false, + '5.2.3' => true, + ), + ), + 'htmlspecialchars' => array( + 3 => array( + 'name' => 'double_encode', + '5.2.2' => false, + '5.2.3' => true, + ), + ), + 'http_build_query' => array( + 2 => array( + 'name' => 'arg_separator', + '5.1.1' => false, + '5.1.2' => true, + ), + 3 => array( + 'name' => 'enc_type', + '5.3' => false, + '5.4' => true, + ), + ), + 'idn_to_ascii' => array( + 2 => array( + 'name' => 'variant', + '5.3' => false, + '5.4' => true, + ), + 3 => array( + 'name' => 'idna_info', + '5.3' => false, + '5.4' => true, + ), + ), + 'idn_to_utf8' => array( + 2 => array( + 'name' => 'variant', + '5.3' => false, + '5.4' => true, + ), + 3 => array( + 'name' => 'idna_info', + '5.3' => false, + '5.4' => true, + ), + ), + 'imagecolorset' => array( + 5 => array( + 'name' => 'alpha', + '5.3' => false, + '5.4' => true, + ), + ), + 'imagepng' => array( + 2 => array( + 'name' => 'quality', + '5.1.1' => false, + '5.1.2' => true, + ), + 3 => array( + 'name' => 'filters', + '5.1.2' => false, + '5.1.3' => true, + ), + ), + 'imagerotate' => array( + 3 => array( + 'name' => 'ignore_transparent', + '5.0' => false, + '5.1' => true, + ), + ), + 'imap_open' => array( + 4 => array( + 'name' => 'n_retries', + '5.1' => false, + '5.2' => true, + ), + 5 => array( + 'name' => 'params', + '5.3.1' => false, + '5.3.2' => true, + ), + ), + 'imap_reopen' => array( + 3 => array( + 'name' => 'n_retries', + '5.1' => false, + '5.2' => true, + ), + ), + 'ini_get_all' => array( + 1 => array( + 'name' => 'details', + '5.2' => false, + '5.3' => true, + ), + ), + 'is_a' => array( + 2 => array( + 'name' => 'allow_string', + '5.3.8' => false, + '5.3.9' => true, + ), + ), + 'is_subclass_of' => array( + 2 => array( + 'name' => 'allow_string', + '5.3.8' => false, + '5.3.9' => true, + ), + ), + 'iterator_to_array' => array( + 1 => array( + 'name' => 'use_keys', + '5.2.0' => false, + '5.2.1' => true, + ), + ), + 'json_decode' => array( + 2 => array( + 'name' => 'depth', + '5.2' => false, + '5.3' => true, + ), + 3 => array( + 'name' => 'options', + '5.3' => false, + '5.4' => true, + ), + ), + 'json_encode' => array( + 1 => array( + 'name' => 'options', + '5.2' => false, + '5.3' => true, + ), + 2 => array( + 'name' => 'depth', + '5.4' => false, + '5.5' => true, + ), + ), + 'ldap_add' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_compare' => array( + 4 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_delete' => array( + 2 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_list' => array( + 8 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_mod_add' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_mod_del' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_mod_replace' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_modify_batch' => array( + 3 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_parse_result' => array( + 6 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_read' => array( + 8 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_rename' => array( + 5 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'ldap_search' => array( + 8 => array( + 'name' => 'serverctrls', + '7.2' => false, + '7.3' => true, + ), + ), + 'memory_get_peak_usage' => array( + 0 => array( + 'name' => 'real_usage', + '5.1' => false, + '5.2' => true, + ), + ), + 'memory_get_usage' => array( + 0 => array( + 'name' => 'real_usage', + '5.1' => false, + '5.2' => true, + ), + ), + 'mb_encode_numericentity' => array( + 3 => array( + 'name' => 'is_hex', + '5.3' => false, + '5.4' => true, + ), + ), + 'mb_strrpos' => array( + /* + * Note: the actual position is 2, but the original 3rd + * parameter 'encoding' was moved to the 4th position. + * So the only way to detect if offset is used is when + * both offset and encoding are set. + */ + 3 => array( + 'name' => 'offset', + '5.1' => false, + '5.2' => true, + ), + ), + 'mssql_connect' => array( + 3 => array( + 'name' => 'new_link', + '5.0' => false, + '5.1' => true, + ), + ), + 'mysqli_commit' => array( + 1 => array( + 'name' => 'flags', + '5.4' => false, + '5.5' => true, + ), + 2 => array( + 'name' => 'name', + '5.4' => false, + '5.5' => true, + ), + ), + 'mysqli_rollback' => array( + 1 => array( + 'name' => 'flags', + '5.4' => false, + '5.5' => true, + ), + 2 => array( + 'name' => 'name', + '5.4' => false, + '5.5' => true, + ), + ), + 'nl2br' => array( + 1 => array( + 'name' => 'is_xhtml', + '5.2' => false, + '5.3' => true, + ), + ), + 'openssl_decrypt' => array( + 4 => array( + 'name' => 'iv', + '5.3.2' => false, + '5.3.3' => true, + ), + 5 => array( + 'name' => 'tag', + '7.0' => false, + '7.1' => true, + ), + 6 => array( + 'name' => 'aad', + '7.0' => false, + '7.1' => true, + ), + ), + 'openssl_encrypt' => array( + 4 => array( + 'name' => 'iv', + '5.3.2' => false, + '5.3.3' => true, + ), + 5 => array( + 'name' => 'tag', + '7.0' => false, + '7.1' => true, + ), + 6 => array( + 'name' => 'aad', + '7.0' => false, + '7.1' => true, + ), + 7 => array( + 'name' => 'tag_length', + '7.0' => false, + '7.1' => true, + ), + ), + 'openssl_open' => array( + 4 => array( + 'name' => 'method', + '5.2' => false, + '5.3' => true, + ), + 5 => array( + 'name' => 'iv', + '5.6' => false, + '7.0' => true, + ), + ), + 'openssl_pkcs7_verify' => array( + 5 => array( + 'name' => 'content', + '5.0' => false, + '5.1' => true, + ), + 6 => array( + 'name' => 'p7bfilename', + '7.1' => false, + '7.2' => true, + ), + ), + 'openssl_seal' => array( + 4 => array( + 'name' => 'method', + '5.2' => false, + '5.3' => true, + ), + 5 => array( + 'name' => 'iv', + '5.6' => false, + '7.0' => true, + ), + ), + 'openssl_verify' => array( + 3 => array( + 'name' => 'signature_alg', + '5.1' => false, + '5.2' => true, + ), + ), + 'parse_ini_file' => array( + 2 => array( + 'name' => 'scanner_mode', + '5.2' => false, + '5.3' => true, + ), + ), + 'parse_url' => array( + 1 => array( + 'name' => 'component', + '5.1.1' => false, + '5.1.2' => true, + ), + ), + 'pg_fetch_all' => array( + 1 => array( + 'name' => 'result_type', + '7.0' => false, + '7.1' => true, + ), + ), + 'pg_last_notice' => array( + 1 => array( + 'name' => 'option', + '7.0' => false, + '7.1' => true, + ), + ), + 'pg_lo_create' => array( + 1 => array( + 'name' => 'object_id', + '5.2' => false, + '5.3' => true, + ), + ), + 'pg_lo_import' => array( + 2 => array( + 'name' => 'object_id', + '5.2' => false, + '5.3' => true, + ), + ), + 'pg_select' => array( + 4 => array( + 'name' => 'result_type', + '7.0' => false, + '7.1' => true, + ), + ), + 'php_uname' => array( + 0 => array( + 'name' => 'mode', + '4.2' => false, + '4.3' => true, + ), + ), + 'preg_replace' => array( + 4 => array( + 'name' => 'count', + '5.0' => false, + '5.1' => true, + ), + ), + 'preg_replace_callback' => array( + 4 => array( + 'name' => 'count', + '5.0' => false, + '5.1' => true, + ), + 5 => array( + 'name' => 'flags', + '7.3' => false, + '7.4' => true, + ), + ), + 'preg_replace_callback_array' => array( + 4 => array( + 'name' => 'flags', + '7.3' => false, + '7.4' => true, + ), + ), + 'round' => array( + 2 => array( + 'name' => 'mode', + '5.2' => false, + '5.3' => true, + ), + ), + 'sem_acquire' => array( + 1 => array( + 'name' => 'nowait', + '5.6' => false, + '5.6.1' => true, + ), + ), + 'session_regenerate_id' => array( + 0 => array( + 'name' => 'delete_old_session', + '5.0' => false, + '5.1' => true, + ), + ), + 'session_set_cookie_params' => array( + 4 => array( + 'name' => 'httponly', + '5.1' => false, + '5.2' => true, + ), + ), + 'session_set_save_handler' => array( + 6 => array( + 'name' => 'create_sid', + '5.5.0' => false, + '5.5.1' => true, + ), + 7 => array( + 'name' => 'validate_sid', + '5.6' => false, + '7.0' => true, + ), + 8 => array( + 'name' => 'update_timestamp', + '5.6' => false, + '7.0' => true, + ), + ), + 'session_start' => array( + 0 => array( + 'name' => 'options', + '5.6' => false, + '7.0' => true, + ), + ), + 'setcookie' => array( + 6 => array( + 'name' => 'httponly', + '5.1' => false, + '5.2' => true, + ), + ), + 'setrawcookie' => array( + 6 => array( + 'name' => 'httponly', + '5.1' => false, + '5.2' => true, + ), + ), + 'simplexml_load_file' => array( + 4 => array( + 'name' => 'is_prefix', + '5.1' => false, + '5.2' => true, + ), + ), + 'simplexml_load_string' => array( + 4 => array( + 'name' => 'is_prefix', + '5.1' => false, + '5.2' => true, + ), + ), + 'spl_autoload_register' => array( + 2 => array( + 'name' => 'prepend', + '5.2' => false, + '5.3' => true, + ), + ), + 'stream_context_create' => array( + 1 => array( + 'name' => 'params', + '5.2' => false, + '5.3' => true, + ), + ), + 'stream_copy_to_stream' => array( + 3 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + ), + 'stream_get_contents' => array( + 2 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + ), + 'stream_wrapper_register' => array( + 2 => array( + 'name' => 'flags', + '5.2.3' => false, + '5.2.4' => true, + ), + ), + 'stristr' => array( + 2 => array( + 'name' => 'before_needle', + '5.2' => false, + '5.3' => true, + ), + ), + 'strstr' => array( + 2 => array( + 'name' => 'before_needle', + '5.2' => false, + '5.3' => true, + ), + ), + 'str_word_count' => array( + 2 => array( + 'name' => 'charlist', + '5.0' => false, + '5.1' => true, + ), + ), + 'substr_count' => array( + 2 => array( + 'name' => 'offset', + '5.0' => false, + '5.1' => true, + ), + 3 => array( + 'name' => 'length', + '5.0' => false, + '5.1' => true, + ), + ), + 'sybase_connect' => array( + 5 => array( + 'name' => 'new', + '5.2' => false, + '5.3' => true, + ), + ), + 'timezone_transitions_get' => array( + 1 => array( + 'name' => 'timestamp_begin', + '5.2' => false, + '5.3' => true, + ), + 2 => array( + 'name' => 'timestamp_end', + '5.2' => false, + '5.3' => true, + ), + ), + 'timezone_identifiers_list' => array( + 0 => array( + 'name' => 'what', + '5.2' => false, + '5.3' => true, + ), + 1 => array( + 'name' => 'country', + '5.2' => false, + '5.3' => true, + ), + ), + 'token_get_all' => array( + 1 => array( + 'name' => 'flags', + '5.6' => false, + '7.0' => true, + ), + ), + 'ucwords' => array( + 1 => array( + 'name' => 'delimiters', + '5.4.31' => false, + '5.5.15' => false, + '5.4.32' => true, + '5.5.16' => true, + ), + ), + 'unpack' => array( + 2 => array( + 'name' => 'offset', + '7.0' => false, + '7.1' => true, + ), + ), + 'unserialize' => array( + 1 => array( + 'name' => 'options', + '5.6' => false, + '7.0' => true, + ), + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->newFunctionParameters = $this->arrayKeysToLowercase($this->newFunctionParameters); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->newFunctionParameters[$functionLc]) === false) { + return; + } + + $parameterCount = $this->getFunctionCallParameterCount($phpcsFile, $stackPtr); + if ($parameterCount === 0) { + return; + } + + // If the parameter count returned > 0, we know there will be valid open parenthesis. + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + $parameterOffsetFound = $parameterCount - 1; + + foreach ($this->newFunctionParameters[$functionLc] as $offset => $parameterDetails) { + if ($offset <= $parameterOffsetFound) { + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + 'offset' => $offset, + ); + $this->handleFeature($phpcsFile, $openParenthesis, $itemInfo); + } + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newFunctionParameters[$itemInfo['nameLc']][$itemInfo['offset']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('name'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Get the item name to be used for the creation of the error code. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Detail information about an item. + * + * @return string + */ + protected function getItemName(array $itemInfo, array $errorInfo) + { + return $itemInfo['name'] . '_' . $errorInfo['paramName']; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The function %s() does not have a parameter "%s" in PHP version %s or earlier'; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + array_shift($data); + array_unshift($data, $itemInfo['name'], $errorInfo['paramName']); + return $data; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php new file mode 100644 index 000000000..c1a0ec4e5 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/NewFunctionsSniff.php @@ -0,0 +1,2008 @@ + array(string => bool)) + */ + protected $newFunctions = array( + 'iterator_count' => array( + '5.0' => false, + '5.1' => true, + ), + 'iterator_to_array' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_call' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_extensions' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_functions' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_register' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload_unregister' => array( + '5.0' => false, + '5.1' => true, + ), + 'spl_autoload' => array( + '5.0' => false, + '5.1' => true, + ), + 'hash_hmac' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'array_fill_keys' => array( + '5.1' => false, + '5.2' => true, + ), + 'error_get_last' => array( + '5.1' => false, + '5.2' => true, + ), + 'image_type_to_extension' => array( + '5.1' => false, + '5.2' => true, + ), + 'memory_get_peak_usage' => array( + '5.1' => false, + '5.2' => true, + ), + 'sys_get_temp_dir' => array( + '5.1' => false, + '5.2' => true, + ), + 'timezone_abbreviations_list' => array( + '5.1' => false, + '5.2' => true, + ), + 'timezone_identifiers_list' => array( + '5.1' => false, + '5.2' => true, + ), + 'timezone_name_from_abbr' => array( + '5.1' => false, + '5.2' => true, + ), + 'stream_socket_shutdown' => array( + '5.1' => false, + '5.2' => true, + ), + 'imagegrabscreen' => array( + '5.1' => false, + '5.2' => true, + ), + 'imagegrabwindow' => array( + '5.1' => false, + '5.2' => true, + ), + 'libxml_disable_entity_loader' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_stripos' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_stristr' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_strrchr' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_strrichr' => array( + '5.1' => false, + '5.2' => true, + ), + 'mb_strripos' => array( + '5.1' => false, + '5.2' => true, + ), + 'ming_setSWFCompression' => array( + '5.1' => false, + '5.2' => true, + ), + 'openssl_csr_get_public_key' => array( + '5.1' => false, + '5.2' => true, + ), + 'openssl_csr_get_subject' => array( + '5.1' => false, + '5.2' => true, + ), + 'openssl_pkey_get_details' => array( + '5.1' => false, + '5.2' => true, + ), + 'spl_object_hash' => array( + '5.1' => false, + '5.2' => true, + ), + 'iterator_apply' => array( + '5.1' => false, + '5.2' => true, + ), + 'preg_last_error' => array( + '5.1' => false, + '5.2' => true, + ), + 'pg_field_table' => array( + '5.1' => false, + '5.2' => true, + ), + 'posix_initgroups' => array( + '5.1' => false, + '5.2' => true, + ), + 'gmp_nextprime' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_full_end_element' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_write_raw' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_start_dtd_entity' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_end_dtd_entity' => array( + '5.1' => false, + '5.2' => true, + ), + 'xmlwriter_write_dtd_entity' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_has_var' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_id' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_input_array' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_input' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_list' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_var_array' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter_var' => array( + '5.1' => false, + '5.2' => true, + ), + 'json_decode' => array( + '5.1' => false, + '5.2' => true, + ), + 'json_encode' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_close' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_close' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_compressedsize' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_compressionmethod' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_filesize' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_name' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_open' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_entry_read' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_open' => array( + '5.1' => false, + '5.2' => true, + ), + 'zip_read' => array( + '5.1' => false, + '5.2' => true, + ), + + 'array_replace' => array( + '5.2' => false, + '5.3' => true, + ), + 'array_replace_recursive' => array( + '5.2' => false, + '5.3' => true, + ), + 'class_alias' => array( + '5.2' => false, + '5.3' => true, + ), + 'forward_static_call' => array( + '5.2' => false, + '5.3' => true, + ), + 'forward_static_call_array' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_collect_cycles' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_disable' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_enable' => array( + '5.2' => false, + '5.3' => true, + ), + 'gc_enabled' => array( + '5.2' => false, + '5.3' => true, + ), + 'get_called_class' => array( + '5.2' => false, + '5.3' => true, + ), + 'gethostname' => array( + '5.2' => false, + '5.3' => true, + ), + 'header_remove' => array( + '5.2' => false, + '5.3' => true, + ), + 'lcfirst' => array( + '5.2' => false, + '5.3' => true, + ), + 'parse_ini_string' => array( + '5.2' => false, + '5.3' => true, + ), + 'quoted_printable_encode' => array( + '5.2' => false, + '5.3' => true, + ), + 'str_getcsv' => array( + '5.2' => false, + '5.3' => true, + ), + 'stream_context_set_default' => array( + '5.2' => false, + '5.3' => true, + ), + 'stream_supports_lock' => array( + '5.2' => false, + '5.3' => true, + ), + 'stream_context_get_params' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_add' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_create_from_format' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_diff' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_get_last_errors' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_parse_from_format' => array( + '5.2' => false, + '5.3' => true, + ), + 'date_sub' => array( + '5.2' => false, + '5.3' => true, + ), + 'timezone_version_get' => array( + '5.2' => false, + '5.3' => true, + ), + 'gmp_testbit' => array( + '5.2' => false, + '5.3' => true, + ), + 'hash_copy' => array( + '5.2' => false, + '5.3' => true, + ), + 'imap_gc' => array( + '5.2' => false, + '5.3' => true, + ), + 'imap_utf8_to_mutf7' => array( + '5.2' => false, + '5.3' => true, + ), + 'imap_mutf7_to_utf8' => array( + '5.2' => false, + '5.3' => true, + ), + 'json_last_error' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_get_cache_stats' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_fetch_all' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_get_connection_status' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_poll' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli_read_async_query' => array( + '5.2' => false, + '5.3' => true, + ), + 'openssl_random_pseudo_bytes' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_signal_dispatch' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_sigprocmask' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_sigtimedwait' => array( + '5.2' => false, + '5.3' => true, + ), + 'pcntl_sigwaitinfo' => array( + '5.2' => false, + '5.3' => true, + ), + 'preg_filter' => array( + '5.2' => false, + '5.3' => true, + ), + 'msg_queue_exists' => array( + '5.2' => false, + '5.3' => true, + ), + 'shm_has_vars' => array( + '5.2' => false, + '5.3' => true, + ), + 'acosh' => array( + '5.2' => false, + '5.3' => true, + ), + 'asinh' => array( + '5.2' => false, + '5.3' => true, + ), + 'atanh' => array( + '5.2' => false, + '5.3' => true, + ), + 'expm1' => array( + '5.2' => false, + '5.3' => true, + ), + 'log1p' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_describe' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_dict_exists' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_free_dict' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_free' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_get_error' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_init' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_list_dicts' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_request_dict' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_request_pwl_dict' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_broker_set_ordering' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_add_to_personal' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_add_to_session' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_check' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_describe' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_get_error' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_is_in_session' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_quick_check' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_store_replacement' => array( + '5.2' => false, + '5.3' => true, + ), + 'enchant_dict_suggest' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_buffer' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_close' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_file' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_open' => array( + '5.2' => false, + '5.3' => true, + ), + 'finfo_set_flags' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_error_name' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_get_error_code' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_get_error_message' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl_is_failure' => array( + '5.2' => false, + '5.3' => true, + ), + + 'hex2bin' => array( + '5.3' => false, + '5.4' => true, + ), + 'http_response_code' => array( + '5.3' => false, + '5.4' => true, + ), + 'get_declared_traits' => array( + '5.3' => false, + '5.4' => true, + ), + 'getimagesizefromstring' => array( + '5.3' => false, + '5.4' => true, + ), + 'stream_set_chunk_size' => array( + '5.3' => false, + '5.4' => true, + ), + 'socket_import_stream' => array( + '5.3' => false, + '5.4' => true, + ), + 'trait_exists' => array( + '5.3' => false, + '5.4' => true, + ), + 'header_register_callback' => array( + '5.3' => false, + '5.4' => true, + ), + 'class_uses' => array( + '5.3' => false, + '5.4' => true, + ), + 'session_status' => array( + '5.3' => false, + '5.4' => true, + ), + 'session_register_shutdown' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqli_error_list' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqli_stmt_error_list' => array( + '5.3' => false, + '5.4' => true, + ), + 'libxml_set_external_entity_loader' => array( + '5.3' => false, + '5.4' => true, + ), + 'ldap_control_paged_result' => array( + '5.3' => false, + '5.4' => true, + ), + 'ldap_control_paged_result_response' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_create' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_create_from_rules' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_create_inverse' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_get_error_code' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_get_error_message' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_list_ids' => array( + '5.3' => false, + '5.4' => true, + ), + 'transliteral_transliterate' => array( + '5.3' => false, + '5.4' => true, + ), + 'zlib_decode' => array( + '5.3' => false, + '5.4' => true, + ), + 'zlib_encode' => array( + '5.3' => false, + '5.4' => true, + ), + + 'array_column' => array( + '5.4' => false, + '5.5' => true, + ), + 'boolval' => array( + '5.4' => false, + '5.5' => true, + ), + 'json_last_error_msg' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_get_info' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_hash' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_needs_rehash' => array( + '5.4' => false, + '5.5' => true, + ), + 'password_verify' => array( + '5.4' => false, + '5.5' => true, + ), + 'hash_pbkdf2' => array( + '5.4' => false, + '5.5' => true, + ), + 'openssl_pbkdf2' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_escape' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_file_create' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_multi_setopt' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_multi_strerror' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_pause' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_reset' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_share_close' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_share_init' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_share_setopt' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_strerror' => array( + '5.4' => false, + '5.5' => true, + ), + 'curl_unescape' => array( + '5.4' => false, + '5.5' => true, + ), + 'imageaffinematrixconcat' => array( + '5.4' => false, + '5.5' => true, + ), + 'imageaffinematrixget' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagecrop' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagecropauto' => array( + '5.4' => false, + '5.5' => true, + ), + 'imageflip' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagepalettetotruecolor' => array( + '5.4' => false, + '5.5' => true, + ), + 'imagescale' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqli_begin_transaction' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqli_release_savepoint' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqli_savepoint' => array( + '5.4' => false, + '5.5' => true, + ), + 'pg_escape_literal' => array( + '5.4' => false, + '5.5' => true, + ), + 'pg_escape_identifier' => array( + '5.4' => false, + '5.5' => true, + ), + 'socket_sendmsg' => array( + '5.4' => false, + '5.5' => true, + ), + 'socket_recvmsg' => array( + '5.4' => false, + '5.5' => true, + ), + 'socket_cmsg_space' => array( + '5.4' => false, + '5.5' => true, + ), + 'cli_get_process_title' => array( + '5.4' => false, + '5.5' => true, + ), + 'cli_set_process_title' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_format_object' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_get_calendar_object' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_get_timezone' => array( + '5.4' => false, + '5.5' => true, + ), + 'datefmt_set_timezone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_create_instance' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_keyword_values_for_locale' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_now' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_available_locales' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_add' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_after' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_before' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_roll' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_clear' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_field_difference' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_actual_maximum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_actual_minumum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_day_of_week_type' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_first_day_of_week' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_greatest_minimum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_least_maximum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_locale' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_maximum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_minimal_days_in_first_week' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_minimum' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_type' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_weekend_transition' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_in_daylight_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_is_equivalent_to' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_is_lenient' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_equals' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_repeated_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_skipped_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_repeated_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_set_skipped_wall_time_option' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_from_date_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_to_date_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_error_code' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlcal_get_error_message' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_create_instance' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_set_gregorian_change' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_get_gregorian_change' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlgregcal_is_leap_year' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_default' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_id' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_gmt' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_unknown' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_enumeration' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_count_equivalent_ids' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_create_time_zone_id_enumeration' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_canonical_id' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_region' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_tz_data_version' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_equivalent_id' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_use_daylight_time' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_offset' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_raw_offset' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_has_same_rules' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_display_name' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_dst_savings' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_from_date_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_to_date_time_zone' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_error_code' => array( + '5.4' => false, + '5.5' => true, + ), + 'intlz_get_error_message' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_compile_file' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_get_configuration' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_get_status' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_invalidate' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache_reset' => array( + '5.4' => false, + '5.5' => true, + ), + + 'opcache_is_script_cached' => array( + '5.5.10' => false, + '5.5.11' => true, + ), + + 'gmp_root' => array( + '5.5' => false, + '5.6' => true, + ), + 'gmp_rootrem' => array( + '5.5' => false, + '5.6' => true, + ), + 'hash_equals' => array( + '5.5' => false, + '5.6' => true, + ), + 'ldap_escape' => array( + '5.5' => false, + '5.6' => true, + ), + 'ldap_modify_batch' => array( + '5.4.25' => false, + '5.5.9' => false, + '5.4.26' => true, + '5.5.10' => true, + '5.6.0' => true, + ), + 'mysqli_get_links_stats' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_get_cert_locations' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_x509_fingerprint' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_new' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_verify' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_export_challenge' => array( + '5.5' => false, + '5.6' => true, + ), + 'openssl_spki_export' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_connect_poll' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_consume_input' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_flush' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_lo_truncate' => array( + '5.5' => false, + '5.6' => true, + ), + 'pg_socket' => array( + '5.5' => false, + '5.6' => true, + ), + 'session_abort' => array( + '5.5' => false, + '5.6' => true, + ), + 'session_reset' => array( + '5.5' => false, + '5.6' => true, + ), + + 'random_bytes' => array( + '5.6' => false, + '7.0' => true, + ), + 'random_int' => array( + '5.6' => false, + '7.0' => true, + ), + 'error_clear_last' => array( + '5.6' => false, + '7.0' => true, + ), + 'gmp_random_seed' => array( + '5.6' => false, + '7.0' => true, + ), + 'intdiv' => array( + '5.6' => false, + '7.0' => true, + ), + 'preg_replace_callback_array' => array( + '5.6' => false, + '7.0' => true, + ), + 'gc_mem_caches' => array( + '5.6' => false, + '7.0' => true, + ), + 'get_resources' => array( + '5.6' => false, + '7.0' => true, + ), + 'posix_setrlimit' => array( + '5.6' => false, + '7.0' => true, + ), + 'inflate_add' => array( + '5.6' => false, + '7.0' => true, + ), + 'deflate_add' => array( + '5.6' => false, + '7.0' => true, + ), + 'inflate_init' => array( + '5.6' => false, + '7.0' => true, + ), + 'deflate_init' => array( + '5.6' => false, + '7.0' => true, + ), + + 'socket_export_stream' => array( + '7.0.6' => false, + '7.0.7' => true, + ), + + 'curl_multi_errno' => array( + '7.0' => false, + '7.1' => true, + ), + 'curl_share_errno' => array( + '7.0' => false, + '7.1' => true, + ), + 'curl_share_strerror' => array( + '7.0' => false, + '7.1' => true, + ), + 'is_iterable' => array( + '7.0' => false, + '7.1' => true, + ), + 'pcntl_async_signals' => array( + '7.0' => false, + '7.1' => true, + ), + 'pcntl_signal_get_handler' => array( + '7.0' => false, + '7.1' => true, + ), + 'session_create_id' => array( + '7.0' => false, + '7.1' => true, + ), + 'session_gc' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_set' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_get' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_is_utf8' => array( + '7.0' => false, + '7.1' => true, + ), + 'sapi_windows_cp_conv' => array( + '7.0' => false, + '7.1' => true, + ), + + 'hash_hkdf' => array( + '7.1.1' => false, + '7.1.2' => true, + ), + 'oci_register_taf_callback' => array( + '7.1.6' => false, + '7.1.7' => true, + ), + 'oci_unregister_taf_callback' => array( + '7.1.8' => false, + '7.1.9' => true, + ), + + 'stream_isatty' => array( + '7.1' => false, + '7.2' => true, + ), + 'sapi_windows_vt100_support' => array( + '7.1' => false, + '7.2' => true, + ), + 'ftp_append' => array( + '7.1' => false, + '7.2' => true, + ), + 'hash_hmac_algos' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagebmp' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagecreatefrombmp' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagegetclip' => array( + '7.1' => false, + '7.2' => true, + ), + 'imageopenpolygon' => array( + '7.1' => false, + '7.2' => true, + ), + 'imageresolution' => array( + '7.1' => false, + '7.2' => true, + ), + 'imagesetclip' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_exop' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_exop_passwd' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_exop_whoami' => array( + '7.1' => false, + '7.2' => true, + ), + 'ldap_parse_exop' => array( + '7.1' => false, + '7.2' => true, + ), + 'mb_chr' => array( + '7.1' => false, + '7.2' => true, + ), + 'mb_ord' => array( + '7.1' => false, + '7.2' => true, + ), + 'mb_scrub' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_lookup' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_connect' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_bind' => array( + '7.1' => false, + '7.2' => true, + ), + 'socket_addrinfo_explain' => array( + '7.1' => false, + '7.2' => true, + ), + 'spl_object_id' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_add' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_base642bin' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_bin2base64' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_bin2hex' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_compare' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_is_available' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_aes256gcm_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_ietf_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_ietf_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_chacha20poly1305_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_xchacha20poly1305_ietf_decrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_aead_xchacha20poly1305_ietf_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_auth_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_auth_verify' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_auth' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_keypair_from_secretkey_and_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_publickey_from_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_seal_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_seal' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box_seed_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_box' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_final' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_init' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash_update' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_generichash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kdf_derive_from_key' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kdf_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_client_session_keys' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_seed_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_kx_server_session_keys' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_scryptsalsa208sha256_str_verify' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_scryptsalsa208sha256_str' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_scryptsalsa208sha256' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_str_needs_rehash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_str_verify' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash_str' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_pwhash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_scalarmult_base' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_scalarmult' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretbox_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretbox_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretbox' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_init_push' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_pull' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_push' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_secretstream_xchacha20poly1305_rekey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_shorthash_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_shorthash' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_detached' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_ed25519_pk_to_curve25519' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_ed25519_sk_to_curve25519' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_keypair_from_secretkey_and_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_open' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_publickey_from_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_publickey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_secretkey' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_seed_keypair' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign_verify_detached' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_sign' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_stream_keygen' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_stream_xor' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_crypto_stream' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_hex2bin' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_increment' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_memcmp' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_memzero' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_pad' => array( + '7.1' => false, + '7.2' => true, + ), + 'sodium_unpad' => array( + '7.1' => false, + '7.2' => true, + ), + // Introduced in 7.2.14 and 7.3.1 simultanously. + 'oci_set_call_timeout' => array( + '7.2.13' => false, + '7.2.14' => true, + ), + // Introduced in 7.2.14 and 7.3.1 simultanously. + 'oci_set_db_operation' => array( + '7.2.13' => false, + '7.2.14' => true, + ), + + 'hrtime' => array( + '7.2' => false, + '7.3' => true, + ), + 'is_countable' => array( + '7.2' => false, + '7.3' => true, + ), + 'array_key_first' => array( + '7.2' => false, + '7.3' => true, + ), + 'array_key_last' => array( + '7.2' => false, + '7.3' => true, + ), + 'fpm_get_status' => array( + '7.2' => false, + '7.3' => true, + ), + 'net_get_interfaces' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_binomial' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_lcm' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_perfect_power' => array( + '7.2' => false, + '7.3' => true, + ), + 'gmp_kronecker' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_add_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_bind_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_delete_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_exop_refresh' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_mod_add_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_mod_replace_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_mod_del_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'ldap_rename_ext' => array( + '7.2' => false, + '7.3' => true, + ), + 'normalizer_get_raw_decomposition' => array( + '7.2' => false, + '7.3' => true, + ), + 'openssl_pkey_derive' => array( + '7.2' => false, + '7.3' => true, + ), + 'socket_wsaprotocol_info_export' => array( + '7.2' => false, + '7.3' => true, + ), + 'socket_wsaprotocol_info_import' => array( + '7.2' => false, + '7.3' => true, + ), + 'socket_wsaprotocol_info_release' => array( + '7.2' => false, + '7.3' => true, + ), + + 'get_mangled_object_vars' => array( + '7.3' => false, + '7.4' => true, + ), + 'imagecreatefromtga' => array( + '7.3' => false, + '7.4' => true, + ), + 'mb_str_split' => array( + '7.3' => false, + '7.4' => true, + ), + 'openssl_x509_verify' => array( + '7.3' => false, + '7.4' => true, + ), + 'password_algos' => array( + '7.3' => false, + '7.4' => true, + ), + 'pcntl_unshare' => array( + '7.3' => false, + '7.4' => true, + ), + 'sapi_windows_set_ctrl_handler' => array( + '7.3' => false, + '7.4' => true, + ), + 'sapi_windows_generate_ctrl_event' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->newFunctions = $this->arrayKeysToLowercase($this->newFunctions); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + + } elseif ($tokens[$prevToken]['code'] === \T_NS_SEPARATOR && $tokens[$prevToken - 1]['code'] === \T_STRING) { + // Namespaced function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->newFunctions[$functionLc]) === false) { + return; + } + + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newFunctions[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The function %s() is not present in PHP version %s or earlier'; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php new file mode 100644 index 000000000..301e5e078 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/OptionalToRequiredFunctionParametersSniff.php @@ -0,0 +1,173 @@ + array( + 1 => array( + 'name' => 'salt', + '5.6' => 'recommended', + ), + ), + 'parse_str' => array( + 1 => array( + 'name' => 'result', + '7.2' => false, + ), + ), + ); + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 8.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['optionalDeprecated'] !== '' + || $errorInfo['optionalRemoved'] !== '' + || $errorInfo['optionalRecommended'] !== ''); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 8.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = array( + 'paramName' => '', + 'optionalRecommended' => '', + 'optionalDeprecated' => '', + 'optionalRemoved' => '', + 'error' => false, + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $required) { + if ($this->supportsAbove($version) === true) { + if ($required === true && $errorInfo['optionalRemoved'] === '') { + $errorInfo['optionalRemoved'] = $version; + $errorInfo['error'] = true; + } elseif ($required === 'recommended' && $errorInfo['optionalRecommended'] === '') { + $errorInfo['optionalRecommended'] = $version; + } elseif ($errorInfo['optionalDeprecated'] === '') { + $errorInfo['optionalDeprecated'] = $version; + } + } + } + } + + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Generates the error or warning for this item. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $error = 'The "%s" parameter for function %s() is missing. Passing this parameter is '; + if ($errorInfo['optionalRecommended'] === '') { + $error .= 'no longer optional. The optional nature of the parameter is '; + } else { + $error .= 'strongly recommended '; + } + + $errorCode = $this->stringToErrorCode($itemInfo['name'] . '_' . $errorInfo['paramName']); + $data = array( + $errorInfo['paramName'], + $itemInfo['name'], + ); + + if ($errorInfo['optionalRecommended'] !== '') { + $error .= 'since PHP %s '; + $errorCode .= 'SoftRecommended'; + $data[] = $errorInfo['optionalRecommended']; + } else { + if ($errorInfo['optionalDeprecated'] !== '') { + $error .= 'deprecated since PHP %s and '; + $errorCode .= 'SoftRequired'; + $data[] = $errorInfo['optionalDeprecated']; + } + + if ($errorInfo['optionalRemoved'] !== '') { + $error .= 'removed since PHP %s and '; + $errorCode .= 'HardRequired'; + $data[] = $errorInfo['optionalRemoved']; + } + + // Remove the last 'and' from the message. + $error = substr($error, 0, (\strlen($error) - 5)); + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $errorInfo['error'], $errorCode, $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php new file mode 100644 index 000000000..b4cad10b1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionParametersSniff.php @@ -0,0 +1,292 @@ + array( + 0 => array( + 'name' => 'age', + '7.4' => false, + 'callback' => 'curlVersionInvalidValue', + ), + ), + 'define' => array( + 2 => array( + 'name' => 'case_insensitive', + '7.3' => false, // Slated for removal in PHP 8.0.0. + ), + ), + 'gmmktime' => array( + 6 => array( + 'name' => 'is_dst', + '5.1' => false, + '7.0' => true, + ), + ), + 'ldap_first_attribute' => array( + 2 => array( + 'name' => 'ber_identifier', + '5.2.4' => true, + ), + ), + 'ldap_next_attribute' => array( + 2 => array( + 'name' => 'ber_identifier', + '5.2.4' => true, + ), + ), + 'mktime' => array( + 6 => array( + 'name' => 'is_dst', + '5.1' => false, + '7.0' => true, + ), + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->removedFunctionParameters = $this->arrayKeysToLowercase($this->removedFunctionParameters); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->removedFunctionParameters[$functionLc]) === false) { + return; + } + + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + $parameterCount = \count($parameters); + if ($parameterCount === 0) { + return; + } + + // If the parameter count returned > 0, we know there will be valid open parenthesis. + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + $parameterOffsetFound = $parameterCount - 1; + + foreach ($this->removedFunctionParameters[$functionLc] as $offset => $parameterDetails) { + if ($offset <= $parameterOffsetFound) { + if (isset($parameterDetails['callback']) && method_exists($this, $parameterDetails['callback'])) { + if ($this->{$parameterDetails['callback']}($phpcsFile, $parameters[($offset + 1)]) === false) { + continue; + } + } + + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + 'offset' => $offset, + ); + $this->handleFeature($phpcsFile, $openParenthesis, $itemInfo); + } + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedFunctionParameters[$itemInfo['nameLc']][$itemInfo['offset']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('name', 'callback'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Get the item name to be used for the creation of the error code. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Detail information about an item. + * + * @return string + */ + protected function getItemName(array $itemInfo, array $errorInfo) + { + return $itemInfo['name'] . '_' . $errorInfo['paramName']; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The "%s" parameter for function %s() is '; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + array_shift($data); + array_unshift($data, $errorInfo['paramName'], $itemInfo['name']); + return $data; + } + + /** + * Check whether curl_version() was passed the default CURLVERSION_NOW. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $parameter Parameter info array. + * + * @return bool True if the value was not CURLVERSION_NOW, false otherwise. + */ + protected function curlVersionInvalidValue(File $phpcsFile, array $parameter) + { + $tokens = $phpcsFile->getTokens(); + $raw = ''; + for ($i = $parameter['start']; $i <= $parameter['end']; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']])) { + continue; + } + + $raw .= $tokens[$i]['content']; + } + + if ($raw !== 'CURLVERSION_NOW' + && $raw !== (string) \CURLVERSION_NOW + ) { + return true; + } + + return false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php new file mode 100644 index 000000000..33f3d3936 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RemovedFunctionsSniff.php @@ -0,0 +1,1104 @@ + array(string => bool|string|null)) + */ + protected $removedFunctions = array( + 'php_check_syntax' => array( + '5.0.5' => true, + 'alternative' => null, + ), + + 'pfpro_cleanup' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_init' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_process_raw' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_process' => array( + '5.1' => true, + 'alternative' => null, + ), + 'pfpro_version' => array( + '5.1' => true, + 'alternative' => null, + ), + + 'call_user_method' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'call_user_func()', + ), + 'call_user_method_array' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'call_user_func_array()', + ), + 'define_syslog_variables' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => null, + ), + 'dl' => array( + '5.3' => false, + 'alternative' => null, + ), + 'ereg' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_match()', + ), + 'ereg_replace' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_replace()', + ), + 'eregi' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_match()', + ), + 'eregi_replace' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_replace()', + ), + 'imagepsbbox' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsencodefont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsextendfont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsfreefont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsloadfont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepsslantfont' => array( + '7.0' => true, + 'alternative' => null, + ), + 'imagepstext' => array( + '7.0' => true, + 'alternative' => null, + ), + 'import_request_variables' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => null, + ), + 'ldap_sort' => array( + '7.0' => false, + 'alternative' => null, + ), + 'mcrypt_generic_end' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'mcrypt_generic_deinit()', + ), + 'mysql_db_query' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'mysqli::select_db() and mysqli::query()', + ), + 'mysql_escape_string' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'mysqli::real_escape_string()', + ), + 'mysql_list_dbs' => array( + '5.4' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mysqli_bind_param' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::bind_param()', + ), + 'mysqli_bind_result' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::bind_result()', + ), + 'mysqli_client_encoding' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli::character_set_name()', + ), + 'mysqli_fetch' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::fetch()', + ), + 'mysqli_param_count' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt_param_count()', + ), + 'mysqli_get_metadata' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::result_metadata()', + ), + 'mysqli_send_long_data' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'mysqli_stmt::send_long_data()', + ), + 'magic_quotes_runtime' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => null, + ), + 'session_register' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'session_unregister' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'session_is_registered' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'set_magic_quotes_runtime' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => null, + ), + 'set_socket_blocking' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'stream_set_blocking()', + ), + 'split' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_split()', + ), + 'spliti' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => 'preg_split()', + ), + 'sql_regcase' => array( + '5.3' => false, + '7.0' => true, + 'alternative' => null, + ), + 'php_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'php_egg_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'php_real_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'zend_logo_guid' => array( + '5.5' => true, + 'alternative' => null, + ), + 'datefmt_set_timezone_id' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => 'IntlDateFormatter::setTimeZone()', + ), + 'mcrypt_ecb' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mcrypt_cbc' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mcrypt_cfb' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'mcrypt_ofb' => array( + '5.5' => false, + '7.0' => true, + 'alternative' => null, + ), + 'ocibindbyname' => array( + '5.4' => false, + 'alternative' => 'oci_bind_by_name()', + ), + 'ocicancel' => array( + '5.4' => false, + 'alternative' => 'oci_cancel()', + ), + 'ocicloselob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::close()', + ), + 'ocicollappend' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::append()', + ), + 'ocicollassign' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::assign()', + ), + 'ocicollassignelem' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::assignElem()', + ), + 'ocicollgetelem' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::getElem()', + ), + 'ocicollmax' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::max()', + ), + 'ocicollsize' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::size()', + ), + 'ocicolltrim' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::trim()', + ), + 'ocicolumnisnull' => array( + '5.4' => false, + 'alternative' => 'oci_field_is_null()', + ), + 'ocicolumnname' => array( + '5.4' => false, + 'alternative' => 'oci_field_name()', + ), + 'ocicolumnprecision' => array( + '5.4' => false, + 'alternative' => 'oci_field_precision()', + ), + 'ocicolumnscale' => array( + '5.4' => false, + 'alternative' => 'oci_field_scale()', + ), + 'ocicolumnsize' => array( + '5.4' => false, + 'alternative' => 'oci_field_size()', + ), + 'ocicolumntype' => array( + '5.4' => false, + 'alternative' => 'oci_field_type()', + ), + 'ocicolumntyperaw' => array( + '5.4' => false, + 'alternative' => 'oci_field_type_raw()', + ), + 'ocicommit' => array( + '5.4' => false, + 'alternative' => 'oci_commit()', + ), + 'ocidefinebyname' => array( + '5.4' => false, + 'alternative' => 'oci_define_by_name()', + ), + 'ocierror' => array( + '5.4' => false, + 'alternative' => 'oci_error()', + ), + 'ociexecute' => array( + '5.4' => false, + 'alternative' => 'oci_execute()', + ), + 'ocifetch' => array( + '5.4' => false, + 'alternative' => 'oci_fetch()', + ), + 'ocifetchinto' => array( + '5.4' => false, + 'alternative' => null, + ), + 'ocifetchstatement' => array( + '5.4' => false, + 'alternative' => 'oci_fetch_all()', + ), + 'ocifreecollection' => array( + '5.4' => false, + 'alternative' => 'OCI-Collection::free()', + ), + 'ocifreecursor' => array( + '5.4' => false, + 'alternative' => 'oci_free_statement()', + ), + 'ocifreedesc' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::free()', + ), + 'ocifreestatement' => array( + '5.4' => false, + 'alternative' => 'oci_free_statement()', + ), + 'ociinternaldebug' => array( + '5.4' => false, + 'alternative' => 'oci_internal_debug()', + ), + 'ociloadlob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::load()', + ), + 'ocilogoff' => array( + '5.4' => false, + 'alternative' => 'oci_close()', + ), + 'ocilogon' => array( + '5.4' => false, + 'alternative' => 'oci_connect()', + ), + 'ocinewcollection' => array( + '5.4' => false, + 'alternative' => 'oci_new_collection()', + ), + 'ocinewcursor' => array( + '5.4' => false, + 'alternative' => 'oci_new_cursor()', + ), + 'ocinewdescriptor' => array( + '5.4' => false, + 'alternative' => 'oci_new_descriptor()', + ), + 'ocinlogon' => array( + '5.4' => false, + 'alternative' => 'oci_new_connect()', + ), + 'ocinumcols' => array( + '5.4' => false, + 'alternative' => 'oci_num_fields()', + ), + 'ociparse' => array( + '5.4' => false, + 'alternative' => 'oci_parse()', + ), + 'ociplogon' => array( + '5.4' => false, + 'alternative' => 'oci_pconnect()', + ), + 'ociresult' => array( + '5.4' => false, + 'alternative' => 'oci_result()', + ), + 'ocirollback' => array( + '5.4' => false, + 'alternative' => 'oci_rollback()', + ), + 'ocirowcount' => array( + '5.4' => false, + 'alternative' => 'oci_num_rows()', + ), + 'ocisavelob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::save()', + ), + 'ocisavelobfile' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::import()', + ), + 'ociserverversion' => array( + '5.4' => false, + 'alternative' => 'oci_server_version()', + ), + 'ocisetprefetch' => array( + '5.4' => false, + 'alternative' => 'oci_set_prefetch()', + ), + 'ocistatementtype' => array( + '5.4' => false, + 'alternative' => 'oci_statement_type()', + ), + 'ociwritelobtofile' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::export()', + ), + 'ociwritetemporarylob' => array( + '5.4' => false, + 'alternative' => 'OCI-Lob::writeTemporary()', + ), + 'mysqli_get_cache_stats' => array( + '5.4' => true, + 'alternative' => null, + ), + + 'mcrypt_create_iv' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'random_bytes() or OpenSSL', + ), + 'mcrypt_decrypt' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_algorithms_name' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_block_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_iv_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_key_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_modes_name' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_get_supported_key_sizes' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_is_block_algorithm_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_is_block_algorithm' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_is_block_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_enc_self_test' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_encrypt' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_generic_deinit' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_generic_init' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_generic' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_block_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_cipher_name' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_iv_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_get_key_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_list_algorithms' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_list_modes' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_close' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_get_algo_block_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_get_algo_key_size' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_get_supported_key_sizes' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_is_block_algorithm_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_is_block_algorithm' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_is_block_mode' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_open' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mcrypt_module_self_test' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'mdecrypt_generic' => array( + '7.1' => false, + '7.2' => true, + 'alternative' => 'OpenSSL', + ), + 'jpeg2wbmp' => array( + '7.2' => false, + 'alternative' => 'imagecreatefromjpeg() and imagewbmp()', + ), + 'png2wbmp' => array( + '7.2' => false, + 'alternative' => 'imagecreatefrompng() or imagewbmp()', + ), + 'create_function' => array( + '7.2' => false, + 'alternative' => 'an anonymous function', + ), + 'each' => array( + '7.2' => false, + 'alternative' => 'a foreach loop', + ), + 'gmp_random' => array( + '7.2' => false, + 'alternative' => 'gmp_random_bits() or gmp_random_range()', + ), + 'read_exif_data' => array( + '7.2' => false, + 'alternative' => 'exif_read_data()', + ), + + 'image2wbmp' => array( + '7.3' => false, + 'alternative' => 'imagewbmp()', + ), + 'mbregex_encoding' => array( + '7.3' => false, + 'alternative' => 'mb_regex_encoding()', + ), + 'mbereg' => array( + '7.3' => false, + 'alternative' => 'mb_ereg()', + ), + 'mberegi' => array( + '7.3' => false, + 'alternative' => 'mb_eregi()', + ), + 'mbereg_replace' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_replace()', + ), + 'mberegi_replace' => array( + '7.3' => false, + 'alternative' => 'mb_eregi_replace()', + ), + 'mbsplit' => array( + '7.3' => false, + 'alternative' => 'mb_split()', + ), + 'mbereg_match' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_match()', + ), + 'mbereg_search' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search()', + ), + 'mbereg_search_pos' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_pos()', + ), + 'mbereg_search_regs' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_regs()', + ), + 'mbereg_search_init' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_init()', + ), + 'mbereg_search_getregs' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_getregs()', + ), + 'mbereg_search_getpos' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_getpos()', + ), + 'mbereg_search_setpos' => array( + '7.3' => false, + 'alternative' => 'mb_ereg_search_setpos()', + ), + 'fgetss' => array( + '7.3' => false, + 'alternative' => null, + ), + 'gzgetss' => array( + '7.3' => false, + 'alternative' => null, + ), + + 'convert_cyr_string' => array( + '7.4' => false, + 'alternative' => 'mb_convert_encoding(), iconv() or UConverter', + ), + 'ezmlm_hash' => array( + '7.4' => false, + 'alternative' => null, + ), + 'get_magic_quotes_gpc' => array( + '7.4' => false, + 'alternative' => null, + ), + 'get_magic_quotes_runtime' => array( + '7.4' => false, + 'alternative' => null, + ), + 'hebrevc' => array( + '7.4' => false, + 'alternative' => null, + ), + 'is_real' => array( + '7.4' => false, + 'alternative' => 'is_float()', + ), + 'money_format' => array( + '7.4' => false, + 'alternative' => 'NumberFormatter::formatCurrency()', + ), + 'restore_include_path' => array( + '7.4' => false, + 'alternative' => "ini_restore('include_path')", + ), + 'ibase_add_user' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_affected_rows' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_backup' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_add' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_cancel' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_close' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_create' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_echo' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_get' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_import' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_blob_open' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_close' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_commit_ret' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_commit' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_connect' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_db_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_delete_user' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_drop_db' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_errcode' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_errmsg' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_execute' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_fetch_assoc' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_fetch_object' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_fetch_row' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_field_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_free_event_handler' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_free_query' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_free_result' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_gen_id' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_maintain_db' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_modify_user' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_name_result' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_num_fields' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_num_params' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_param_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_pconnect' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_prepare' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_query' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_restore' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_rollback_ret' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_rollback' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_server_info' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_service_attach' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_service_detach' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_set_event_handler' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_trans' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ibase_wait_event' => array( + '7.4' => true, + 'alternative' => null, + ), + 'ldap_control_paged_result_response' => array( + '7.4' => false, + 'alternative' => 'ldap_search()', + ), + 'ldap_control_paged_result' => array( + '7.4' => false, + 'alternative' => 'ldap_search()', + ), + 'recode_file' => array( + '7.4' => true, + 'alternative' => 'the iconv or mbstring extension', + ), + 'recode_string' => array( + '7.4' => true, + 'alternative' => 'the iconv or mbstring extension', + ), + 'recode' => array( + '7.4' => true, + 'alternative' => 'the iconv or mbstring extension', + ), + 'wddx_add_vars' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_deserialize' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_packet_end' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_packet_start' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_serialize_value' => array( + '7.4' => true, + 'alternative' => null, + ), + 'wddx_serialize_vars' => array( + '7.4' => true, + 'alternative' => null, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->removedFunctions = $this->arrayKeysToLowercase($this->removedFunctions); + + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CLASS => true, + \T_CONST => true, + \T_USE => true, + \T_NS_SEPARATOR => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->removedFunctions[$functionLc]) === false) { + return; + } + + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedFunctions[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'Function %s() is '; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php new file mode 100644 index 000000000..9c32cccac --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/FunctionUse/RequiredToOptionalFunctionParametersSniff.php @@ -0,0 +1,350 @@ + array( + 0 => array( + 'name' => 'array(s) to merge', + '7.3' => true, + '7.4' => false, + ), + ), + 'array_merge_recursive' => array( + 0 => array( + 'name' => 'array(s) to merge', + '7.3' => true, + '7.4' => false, + ), + ), + 'array_push' => array( + 1 => array( + 'name' => 'element to push', + '7.2' => true, + '7.3' => false, + ), + ), + 'array_unshift' => array( + 1 => array( + 'name' => 'element to prepend', + '7.2' => true, + '7.3' => false, + ), + ), + 'bcscale' => array( + 0 => array( + 'name' => 'scale', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_fget' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_fput' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_get' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_fget' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_fput' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_get' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_nb_put' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'ftp_put' => array( + 3 => array( + 'name' => 'mode', + '7.2' => true, + '7.3' => false, + ), + ), + 'getenv' => array( + 0 => array( + 'name' => 'varname', + '7.0' => true, + '7.1' => false, + ), + ), + 'preg_match_all' => array( + 2 => array( + 'name' => 'matches', + '5.3' => true, + '5.4' => false, + ), + ), + 'stream_socket_enable_crypto' => array( + 2 => array( + 'name' => 'crypto_type', + '5.5' => true, + '5.6' => false, + ), + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of function names. + $this->functionParameters = $this->arrayKeysToLowercase($this->functionParameters); + + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + \T_NEW => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $function = $tokens[$stackPtr]['content']; + $functionLc = strtolower($function); + + if (isset($this->functionParameters[$functionLc]) === false) { + return; + } + + $parameterCount = $this->getFunctionCallParameterCount($phpcsFile, $stackPtr); + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true); + + // If the parameter count returned > 0, we know there will be valid open parenthesis. + if ($parameterCount === 0 && $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS) { + return; + } + + $parameterOffsetFound = $parameterCount - 1; + + foreach ($this->functionParameters[$functionLc] as $offset => $parameterDetails) { + if ($offset > $parameterOffsetFound) { + $itemInfo = array( + 'name' => $function, + 'nameLc' => $functionLc, + 'offset' => $offset, + ); + $this->handleFeature($phpcsFile, $openParenthesis, $itemInfo); + } + } + } + + + /** + * Determine whether an error/warning should be thrown for an item based on collected information. + * + * @since 7.1.0 + * + * @param array $errorInfo Detail information about an item. + * + * @return bool + */ + protected function shouldThrowError(array $errorInfo) + { + return ($errorInfo['requiredVersion'] !== ''); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->functionParameters[$itemInfo['nameLc']][$itemInfo['offset']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('name'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = array( + 'paramName' => '', + 'requiredVersion' => '', + ); + + $versionArray = $this->getVersionArray($itemArray); + + if (empty($versionArray) === false) { + foreach ($versionArray as $version => $required) { + if ($required === true && $this->supportsBelow($version) === true) { + $errorInfo['requiredVersion'] = $version; + } + } + } + + $errorInfo['paramName'] = $itemArray['name']; + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The "%s" parameter for function %s() is missing, but was required for PHP version %s and lower'; + } + + + /** + * Generates the error or warning for this item. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the relevant token in + * the stack. + * @param array $itemInfo Base information about the item. + * @param array $errorInfo Array with detail (version) information + * relevant to the item. + * + * @return void + */ + public function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $errorInfo) + { + $error = $this->getErrorMsgTemplate(); + $errorCode = $this->stringToErrorCode($itemInfo['name'] . '_' . $errorInfo['paramName']) . 'Missing'; + $data = array( + $errorInfo['paramName'], + $itemInfo['name'], + $errorInfo['requiredVersion'], + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php new file mode 100644 index 000000000..98ca2461c --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Generators/NewGeneratorReturnSniff.php @@ -0,0 +1,158 @@ + \T_FUNCTION, + \T_CLOSURE => \T_CLOSURE, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + $targets = array( + \T_YIELD, + ); + + /* + * The `yield` keyword was introduced in PHP 5.5 with the token T_YIELD. + * The `yield from` keyword was introduced in PHP 7.0 and tokenizes as + * "T_YIELD T_WHITESPACE T_STRING". + * + * Pre-PHPCS 3.1.0, the T_YIELD token was not correctly back-filled for PHP < 5.5. + * Also, as of PHPCS 3.1.0, the PHPCS tokenizer adds a new T_YIELD_FROM + * token. + * + * So for PHP 5.3-5.4 icw PHPCS < 3.1.0, we need to look for T_STRING with content "yield". + * For PHP 5.5+ we need to look for T_YIELD. + * For PHPCS 3.1.0+, we also need to look for T_YIELD_FROM. + */ + if (version_compare(\PHP_VERSION_ID, '50500', '<') === true + && version_compare(PHPCSHelper::getVersion(), '3.1.0', '<') === true + ) { + $targets[] = \T_STRING; + } + + if (\defined('T_YIELD_FROM')) { + $targets[] = \T_YIELD_FROM; + } + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int Void or a stack pointer to skip forward. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_STRING + && $tokens[$stackPtr]['content'] !== 'yield' + ) { + return; + } + + if (empty($tokens[$stackPtr]['conditions']) === true) { + return; + } + + // Walk the condition from inner to outer to see if we can find a valid function/closure scope. + $conditions = array_reverse($tokens[$stackPtr]['conditions'], true); + foreach ($conditions as $ptr => $type) { + if (isset($this->validConditions[$type]) === true) { + $function = $ptr; + break; + } + } + + if (isset($function) === false) { + // Yield outside function scope, fatal error, but not our concern. + return; + } + + if (isset($tokens[$function]['scope_opener'], $tokens[$function]['scope_closer']) === false) { + // Can't reliably determine start/end of function scope. + return; + } + + $targets = array(\T_RETURN, \T_CLOSURE, \T_FUNCTION, \T_CLASS); + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + $current = $tokens[$function]['scope_opener']; + + while (($current = $phpcsFile->findNext($targets, ($current + 1), $tokens[$function]['scope_closer'])) !== false) { + if ($tokens[$current]['code'] === \T_RETURN) { + $phpcsFile->addError( + 'Returning a final expression from a generator was not supported in PHP 5.6 or earlier', + $current, + 'ReturnFound' + ); + + return $tokens[$function]['scope_closer']; + } + + // Found a nested scope in which return can exist without problems. + if (isset($tokens[$current]['scope_closer'])) { + // Skip past the nested scope. + $current = $tokens[$current]['scope_closer']; + } + } + + // Don't examine this function again. + return $tokens[$function]['scope_closer']; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php new file mode 100644 index 000000000..cd40fa687 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/NewIniDirectivesSniff.php @@ -0,0 +1,855 @@ + array( + '4.4' => false, + '5.0' => true, + ), + 'com.code_page' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.default_latitude' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.default_longitude' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.sunrise_zenith' => array( + '4.4' => false, + '5.0' => true, + ), + 'date.sunset_zenith' => array( + '4.4' => false, + '5.0' => true, + ), + 'ibase.default_charset' => array( + '4.4' => false, + '5.0' => true, + ), + 'ibase.default_db' => array( + '4.4' => false, + '5.0' => true, + ), + 'mail.force_extra_parameters' => array( + '4.4' => false, + '5.0' => true, + ), + 'mime_magic.debug' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.max_links' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_port' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_socket' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_host' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_user' => array( + '4.4' => false, + '5.0' => true, + ), + 'mysqli.default_pw' => array( + '4.4' => false, + '5.0' => true, + ), + 'report_zend_debug' => array( + '4.4' => false, + '5.0' => true, + ), + 'session.hash_bits_per_character' => array( + '4.4' => false, + '5.0' => true, + ), + 'session.hash_function' => array( + '4.4' => false, + '5.0' => true, + ), + 'soap.wsdl_cache_dir' => array( + '4.4' => false, + '5.0' => true, + ), + 'soap.wsdl_cache_enabled' => array( + '4.4' => false, + '5.0' => true, + ), + 'soap.wsdl_cache_ttl' => array( + '4.4' => false, + '5.0' => true, + ), + 'sqlite.assoc_case' => array( + '4.4' => false, + '5.0' => true, + ), + 'tidy.clean_output' => array( + '4.4' => false, + '5.0' => true, + ), + 'tidy.default_config' => array( + '4.4' => false, + '5.0' => true, + ), + 'zend.ze1_compatibility_mode' => array( + '4.4' => false, + '5.0' => true, + ), + + 'date.timezone' => array( + '5.0' => false, + '5.1' => true, + ), + 'detect_unicode' => array( + '5.0' => false, + '5.1' => true, + ), + 'fbsql.batchsize' => array( + '5.0' => false, + '5.1' => true, + 'alternative' => 'fbsql.batchSize', + ), + 'realpath_cache_size' => array( + '5.0' => false, + '5.1' => true, + ), + 'realpath_cache_ttl' => array( + '5.0' => false, + '5.1' => true, + ), + + 'mbstring.strict_detection' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + 'mssql.charset' => array( + '5.1.1' => false, + '5.1.2' => true, + ), + + 'gd.jpeg_ignore_warning' => array( + '5.1.2' => false, + '5.1.3' => true, + ), + + 'fbsql.show_timestamp_decimals' => array( + '5.1.4' => false, + '5.1.5' => true, + ), + 'soap.wsdl_cache' => array( + '5.1.4' => false, + '5.1.5' => true, + ), + 'soap.wsdl_cache_limit' => array( + '5.1.4' => false, + '5.1.5' => true, + ), + + 'allow_url_include' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter.default' => array( + '5.1' => false, + '5.2' => true, + ), + 'filter.default_flags' => array( + '5.1' => false, + '5.2' => true, + ), + 'pcre.backtrack_limit' => array( + '5.1' => false, + '5.2' => true, + ), + 'pcre.recursion_limit' => array( + '5.1' => false, + '5.2' => true, + ), + 'session.cookie_httponly' => array( + '5.1' => false, + '5.2' => true, + ), + + 'cgi.check_shebang_line' => array( + '5.2.0' => false, + '5.2.1' => true, + ), + + 'max_input_nesting_level' => array( + '5.2.2' => false, + '5.2.3' => true, + ), + + 'mysqli.allow_local_infile' => array( + '5.2.3' => false, + '5.2.4' => true, + ), + + 'max_file_uploads' => array( + '5.2.11' => false, + '5.2.12' => true, + ), + + 'cgi.discard_path' => array( + '5.2' => false, + '5.3' => true, + ), + 'exit_on_timeout' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl.default_locale' => array( + '5.2' => false, + '5.3' => true, + ), + 'intl.error_level' => array( + '5.2' => false, + '5.3' => true, + ), + 'mail.add_x_header' => array( + '5.2' => false, + '5.3' => true, + ), + 'mail.log' => array( + '5.2' => false, + '5.3' => true, + ), + 'mbstring.http_output_conv_mimetype' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli.allow_persistent' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli.cache_size' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqli.max_persistent' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.collect_memory_statistics' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.collect_statistics' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.debug' => array( + '5.2' => false, + '5.3' => true, + ), + 'mysqlnd.net_read_buffer_size' => array( + '5.2' => false, + '5.3' => true, + ), + 'odbc.default_cursortype' => array( + '5.2' => false, + '5.3' => true, + ), + 'request_order' => array( + '5.2' => false, + '5.3' => true, + ), + 'user_ini.cache_ttl' => array( + '5.2' => false, + '5.3' => true, + ), + 'user_ini.filename' => array( + '5.2' => false, + '5.3' => true, + ), + 'zend.enable_gc' => array( + '5.2' => false, + '5.3' => true, + ), + + 'curl.cainfo' => array( + '5.3.6' => false, + '5.3.7' => true, + ), + + 'max_input_vars' => array( + '5.3.8' => false, + '5.3.9' => true, + ), + + 'sqlite3.extension_dir' => array( + '5.3.10' => false, + '5.3.11' => true, + ), + + 'cli.pager' => array( + '5.3' => false, + '5.4' => true, + ), + 'cli.prompt' => array( + '5.3' => false, + '5.4' => true, + ), + 'cli_server.color' => array( + '5.3' => false, + '5.4' => true, + ), + 'enable_post_data_reading' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.mempool_default_size' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.net_cmd_buffer_size' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.net_read_timeout' => array( + '5.3' => false, + '5.4' => true, + ), + 'phar.cache_list' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.enabled' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.cleanup' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.name' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.freq' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.min_freq' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.upload_progress.prefix' => array( + '5.3' => false, + '5.4' => true, + ), + 'windows_show_crt_warning' => array( + '5.3' => false, + '5.4' => true, + ), + 'zend.detect_unicode' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => 'detect_unicode', + ), + 'zend.multibyte' => array( + '5.3' => false, + '5.4' => true, + ), + 'zend.script_encoding' => array( + '5.3' => false, + '5.4' => true, + ), + 'zend.signal_check' => array( + '5.3' => false, + '5.4' => true, + ), + 'mysqlnd.log_mask' => array( + '5.3' => false, + '5.4' => true, + ), + + 'intl.use_exceptions' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqlnd.sha256_server_public_key' => array( + '5.4' => false, + '5.5' => true, + ), + 'mysqlnd.trace_alloc' => array( + '5.4' => false, + '5.5' => true, + ), + 'sys_temp_dir' => array( + '5.4' => false, + '5.5' => true, + ), + 'xsl.security_prefs' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.enable' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.enable_cli' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.memory_consumption' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.interned_strings_buffer' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.max_accelerated_files' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.max_wasted_percentage' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.use_cwd' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.validate_timestamps' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.revalidate_freq' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.revalidate_path' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.save_comments' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.load_comments' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.fast_shutdown' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.enable_file_override' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.optimization_level' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.inherited_hack' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.dups_fix' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.blacklist_filename' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.max_file_size' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.consistency_checks' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.force_restart_timeout' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.error_log' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.log_verbosity_level' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.preferred_memory_model' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.protect_memory' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.mmap_base' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.restrict_api' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.file_update_protection' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.huge_code_pages' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.lockfile_path' => array( + '5.4' => false, + '5.5' => true, + ), + 'opcache.opt_debug_level' => array( + '5.4' => false, + '5.5' => true, + ), + + 'session.use_strict_mode' => array( + '5.5.1' => false, + '5.5.2' => true, + ), + + 'mysqli.rollback_on_cached_plink' => array( + '5.5' => false, + '5.6' => true, + ), + + 'assert.exception' => array( + '5.6' => false, + '7.0' => true, + ), + 'pcre.jit' => array( + '5.6' => false, + '7.0' => true, + ), + 'session.lazy_write' => array( + '5.6' => false, + '7.0' => true, + ), + 'zend.assertions' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache_only' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache_consistency_checks' => array( + '5.6' => false, + '7.0' => true, + ), + 'opcache.file_cache_fallback' => array( + '5.6' => false, + '7.0' => true, + ), // Windows only. + + 'opcache.validate_permission' => array( + '7.0.13' => false, + '7.0.14' => true, + ), + 'opcache.validate_root' => array( + '7.0.13' => false, + '7.0.14' => true, + ), + + 'hard_timeout' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.sid_length' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.sid_bits_per_character' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.trans_sid_hosts' => array( + '7.0' => false, + '7.1' => true, + ), + 'session.trans_sid_tags' => array( + '7.0' => false, + '7.1' => true, + ), + 'url_rewriter.hosts' => array( + '7.0' => false, + '7.1' => true, + ), + + // Introduced in PHP 7.1.25, 7.2.13, 7.3.0. + 'imap.enable_insecure_rsh' => array( + '7.1.24' => false, + '7.1.25' => true, + ), + + 'syslog.facility' => array( + '7.2' => false, + '7.3' => true, + ), + 'syslog.filter' => array( + '7.2' => false, + '7.3' => true, + ), + 'syslog.ident' => array( + '7.2' => false, + '7.3' => true, + ), + 'session.cookie_samesite' => array( + '7.2' => false, + '7.3' => true, + ), + + 'ffi.enable' => array( + '7.3' => false, + '7.4' => true, + ), + 'ffi.preload' => array( + '7.3' => false, + '7.4' => true, + ), + 'opcache.cache_id' => array( + '7.3' => false, + '7.4' => true, + ), + 'opcache.preload' => array( + '7.3' => false, + '7.4' => true, + ), + 'zend.exception_ignore_args' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $functionLc = strtolower($tokens[$stackPtr]['content']); + if (isset($this->iniFunctions[$functionLc]) === false) { + return; + } + + $iniToken = $this->getFunctionCallParameter($phpcsFile, $stackPtr, $this->iniFunctions[$functionLc]); + if ($iniToken === false) { + return; + } + + $filteredToken = $this->stripQuotes($iniToken['raw']); + if (isset($this->newIniDirectives[$filteredToken]) === false) { + return; + } + + $itemInfo = array( + 'name' => $filteredToken, + 'functionLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $iniToken['end'], $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newIniDirectives[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('alternative'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['alternative'] = ''; + + if (isset($itemArray['alternative']) === true) { + $errorInfo['alternative'] = $itemArray['alternative']; + } + + // Lower error level to warning if the function used was ini_get. + if ($errorInfo['error'] === true && $itemInfo['functionLc'] === 'ini_get') { + $errorInfo['error'] = false; + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "INI directive '%s' is not present in PHP version %s or earlier"; + } + + + /** + * Allow for concrete child classes to filter the error message before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + if ($errorInfo['alternative'] !== '') { + $error .= ". This directive was previously called '%s'."; + } + + return $error; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + if ($errorInfo['alternative'] !== '') { + $data[] = $errorInfo['alternative']; + } + + return $data; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php new file mode 100644 index 000000000..a6928ae08 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/IniDirectives/RemovedIniDirectivesSniff.php @@ -0,0 +1,424 @@ + array( + '5.1' => true, + 'alternative' => 'fbsql.batchsize', + ), + 'pfpro.defaulthost' => array( + '5.1' => true, + ), + 'pfpro.defaultport' => array( + '5.1' => true, + ), + 'pfpro.defaulttimeout' => array( + '5.1' => true, + ), + 'pfpro.proxyaddress' => array( + '5.1' => true, + ), + 'pfpro.proxyport' => array( + '5.1' => true, + ), + 'pfpro.proxylogon' => array( + '5.1' => true, + ), + 'pfpro.proxypassword' => array( + '5.1' => true, + ), + + 'ifx.allow_persistent' => array( + '5.2.1' => true, + ), + 'ifx.blobinfile' => array( + '5.2.1' => true, + ), + 'ifx.byteasvarchar' => array( + '5.2.1' => true, + ), + 'ifx.charasvarchar' => array( + '5.2.1' => true, + ), + 'ifx.default_host' => array( + '5.2.1' => true, + ), + 'ifx.default_password' => array( + '5.2.1' => true, + ), + 'ifx.default_user' => array( + '5.2.1' => true, + ), + 'ifx.max_links' => array( + '5.2.1' => true, + ), + 'ifx.max_persistent' => array( + '5.2.1' => true, + ), + 'ifx.nullformat' => array( + '5.2.1' => true, + ), + 'ifx.textasvarchar' => array( + '5.2.1' => true, + ), + + 'zend.ze1_compatibility_mode' => array( + '5.3' => true, + ), + + 'allow_call_time_pass_reference' => array( + '5.3' => false, + '5.4' => true, + ), + 'define_syslog_variables' => array( + '5.3' => false, + '5.4' => true, + ), + 'detect_unicode' => array( + '5.4' => true, + 'alternative' => 'zend.detect_unicode', + ), + 'highlight.bg' => array( + '5.3' => false, + '5.4' => true, + ), + 'magic_quotes_gpc' => array( + '5.3' => false, + '5.4' => true, + ), + 'magic_quotes_runtime' => array( + '5.3' => false, + '5.4' => true, + ), + 'magic_quotes_sybase' => array( + '5.3' => false, + '5.4' => true, + ), + 'mbstring.script_encoding' => array( + '5.4' => true, + 'alternative' => 'zend.script_encoding', + ), + 'register_globals' => array( + '5.3' => false, + '5.4' => true, + ), + 'register_long_arrays' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_allowed_env_vars' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_exec_dir' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_gid' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_include_dir' => array( + '5.3' => false, + '5.4' => true, + ), + 'safe_mode_protected_env_vars' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.bug_compat_42' => array( + '5.3' => false, + '5.4' => true, + ), + 'session.bug_compat_warn' => array( + '5.3' => false, + '5.4' => true, + ), + 'y2k_compliance' => array( + '5.3' => false, + '5.4' => true, + ), + + 'always_populate_raw_post_data' => array( + '5.6' => false, + '7.0' => true, + ), + 'iconv.input_encoding' => array( + '5.6' => false, + ), + 'iconv.output_encoding' => array( + '5.6' => false, + ), + 'iconv.internal_encoding' => array( + '5.6' => false, + ), + 'mbstring.http_input' => array( + '5.6' => false, + ), + 'mbstring.http_output' => array( + '5.6' => false, + ), + 'mbstring.internal_encoding' => array( + '5.6' => false, + ), + + 'asp_tags' => array( + '7.0' => true, + ), + 'xsl.security_prefs' => array( + '7.0' => true, + ), + 'opcache.load_comments' => array( + '7.0' => true, + ), + + 'mcrypt.algorithms_dir' => array( + '7.1' => false, + '7.2' => true, + ), + 'mcrypt.modes_dir' => array( + '7.1' => false, + '7.2' => true, + ), + 'session.entropy_file' => array( + '7.1' => true, + ), + 'session.entropy_length' => array( + '7.1' => true, + ), + 'session.hash_function' => array( + '7.1' => true, + ), + 'session.hash_bits_per_character' => array( + '7.1' => true, + ), + + 'mbstring.func_overload' => array( + '7.2' => false, + ), + 'sql.safe_mode' => array( + '7.2' => true, + ), + 'track_errors' => array( + '7.2' => false, + ), + 'opcache.fast_shutdown' => array( + '7.2' => true, + ), + + 'birdstep.max_links' => array( + '7.3' => true, + ), + 'opcache.inherited_hack' => array( + '5.3' => false, // Soft deprecated, i.e. ignored. + '7.3' => true, + ), + 'pdo_odbc.db2_instance_name' => array( + '7.3' => false, // Has been marked as deprecated in the manual from before this time. Now hard-deprecated. + ), + + 'allow_url_include' => array( + '7.4' => false, + ), + 'ibase.allow_persistent' => array( + '7.4' => true, + ), + 'ibase.max_persistent' => array( + '7.4' => true, + ), + 'ibase.max_links' => array( + '7.4' => true, + ), + 'ibase.default_db' => array( + '7.4' => true, + ), + 'ibase.default_user' => array( + '7.4' => true, + ), + 'ibase.default_password' => array( + '7.4' => true, + ), + 'ibase.default_charset' => array( + '7.4' => true, + ), + 'ibase.timestampformat' => array( + '7.4' => true, + ), + 'ibase.dateformat' => array( + '7.4' => true, + ), + 'ibase.timeformat' => array( + '7.4' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $functionLc = strtolower($tokens[$stackPtr]['content']); + if (isset($this->iniFunctions[$functionLc]) === false) { + return; + } + + $iniToken = $this->getFunctionCallParameter($phpcsFile, $stackPtr, $this->iniFunctions[$functionLc]); + if ($iniToken === false) { + return; + } + + $filteredToken = $this->stripQuotes($iniToken['raw']); + if (isset($this->deprecatedIniDirectives[$filteredToken]) === false) { + return; + } + + $itemInfo = array( + 'name' => $filteredToken, + 'functionLc' => $functionLc, + ); + $this->handleFeature($phpcsFile, $iniToken['end'], $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->deprecatedIniDirectives[$itemInfo['name']]; + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + + // Lower error level to warning if the function used was ini_get. + if ($errorInfo['error'] === true && $itemInfo['functionLc'] === 'ini_get') { + $errorInfo['error'] = false; + } + + return $errorInfo; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "INI directive '%s' is "; + } + + + /** + * Get the error message template for suggesting an alternative for a specific sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getAlternativeOptionTemplate() + { + return str_replace('%s', "'%s'", parent::getAlternativeOptionTemplate()); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php new file mode 100644 index 000000000..c9c2225f4 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingConstSniff.php @@ -0,0 +1,82 @@ +supportsBelow('5.5') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $find = array( + \T_ARRAY => \T_ARRAY, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + + while (($hasArray = $phpcsFile->findNext($find, ($stackPtr + 1), null, false, null, true)) !== false) { + $phpcsFile->addError( + 'Constant arrays using the "const" keyword are not allowed in PHP 5.5 or earlier', + $hasArray, + 'Found' + ); + + // Skip past the content of the array. + $stackPtr = $hasArray; + if ($tokens[$hasArray]['code'] === \T_OPEN_SHORT_ARRAY && isset($tokens[$hasArray]['bracket_closer'])) { + $stackPtr = $tokens[$hasArray]['bracket_closer']; + } elseif ($tokens[$hasArray]['code'] === \T_ARRAY && isset($tokens[$hasArray]['parenthesis_closer'])) { + $stackPtr = $tokens[$hasArray]['parenthesis_closer']; + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php new file mode 100644 index 000000000..7b996728a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantArraysUsingDefineSniff.php @@ -0,0 +1,101 @@ +supportsBelow('5.6') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $ignore = array( + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_FUNCTION => true, + \T_CONST => true, + ); + + $prevToken = $phpcsFile->findPrevious(\T_WHITESPACE, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function. + return; + } + + $functionLc = strtolower($tokens[$stackPtr]['content']); + if ($functionLc !== 'define') { + return; + } + + $secondParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, 2); + if (isset($secondParam['start'], $secondParam['end']) === false) { + return; + } + + $targetNestingLevel = 0; + if (isset($tokens[$secondParam['start']]['nested_parenthesis'])) { + $targetNestingLevel = \count($tokens[$secondParam['start']]['nested_parenthesis']); + } + + $array = $phpcsFile->findNext(array(\T_ARRAY, \T_OPEN_SHORT_ARRAY), $secondParam['start'], ($secondParam['end'] + 1)); + if ($array !== false) { + if ((isset($tokens[$array]['nested_parenthesis']) === false && $targetNestingLevel === 0) || \count($tokens[$array]['nested_parenthesis']) === $targetNestingLevel) { + $phpcsFile->addError( + 'Constant arrays using define are not allowed in PHP 5.6 or earlier', + $array, + 'Found' + ); + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php new file mode 100644 index 000000000..8e1cddcab --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewConstantScalarExpressionsSniff.php @@ -0,0 +1,556 @@ + 'when defining constants using the const keyword', + 'property' => 'in property declarations', + 'staticvar' => 'in static variable declarations', + 'default' => 'in default function arguments', + ); + + /** + * Tokens which were allowed to be used in these declarations prior to PHP 5.6. + * + * This list will be enriched in the setProperties() method. + * + * @since 8.2.0 + * + * @var array + */ + protected $safeOperands = array( + \T_LNUMBER => \T_LNUMBER, + \T_DNUMBER => \T_DNUMBER, + \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING, + \T_TRUE => \T_TRUE, + \T_FALSE => \T_FALSE, + \T_NULL => \T_NULL, + + \T_LINE => \T_LINE, + \T_FILE => \T_FILE, + \T_DIR => \T_DIR, + \T_FUNC_C => \T_FUNC_C, + \T_CLASS_C => \T_CLASS_C, + \T_TRAIT_C => \T_TRAIT_C, + \T_METHOD_C => \T_METHOD_C, + \T_NS_C => \T_NS_C, + + // Special cases: + \T_NS_SEPARATOR => \T_NS_SEPARATOR, + /* + * This can be neigh anything, but for any usage except constants, + * the T_STRING will be combined with non-allowed tokens, so we should be good. + */ + \T_STRING => \T_STRING, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + // Set the properties up only once. + $this->setProperties(); + + return array( + \T_CONST, + \T_VARIABLE, + \T_FUNCTION, + \T_CLOSURE, + \T_STATIC, + ); + } + + + /** + * Make some adjustments to the $safeOperands property. + * + * @since 8.2.0 + * + * @return void + */ + public function setProperties() + { + $this->safeOperands += Tokens::$heredocTokens; + $this->safeOperands += Tokens::$emptyTokens; + } + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.5') !== true); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int Null or integer stack pointer to skip forward. + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->bowOutEarly() === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + case 'T_FUNCTION': + case 'T_CLOSURE': + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + // No parameters. + return; + } + + $funcToken = $tokens[$stackPtr]; + + if (isset($funcToken['parenthesis_owner'], $funcToken['parenthesis_opener'], $funcToken['parenthesis_closer']) === false + || $funcToken['parenthesis_owner'] !== $stackPtr + || isset($tokens[$funcToken['parenthesis_opener']], $tokens[$funcToken['parenthesis_closer']]) === false + ) { + // Hmm.. something is going wrong as these should all be available & valid. + return; + } + + $opener = $funcToken['parenthesis_opener']; + $closer = $funcToken['parenthesis_closer']; + + // Which nesting level is the one we are interested in ? + $nestedParenthesisCount = 1; + if (isset($tokens[$opener]['nested_parenthesis'])) { + $nestedParenthesisCount += \count($tokens[$opener]['nested_parenthesis']); + } + + foreach ($params as $param) { + if (isset($param['default']) === false) { + continue; + } + + $end = $param['token']; + while (($end = $phpcsFile->findNext(array(\T_COMMA, \T_CLOSE_PARENTHESIS), ($end + 1), ($closer + 1))) !== false) { + $maybeSkipTo = $this->isRealEndOfDeclaration($tokens, $end, $nestedParenthesisCount); + if ($maybeSkipTo !== true) { + $end = $maybeSkipTo; + continue; + } + + // Ignore closing parenthesis/bracket if not 'ours'. + if ($tokens[$end]['code'] === \T_CLOSE_PARENTHESIS && $end !== $closer) { + continue; + } + + // Ok, we've found the end of the param default value declaration. + break; + } + + if ($this->isValidAssignment($phpcsFile, $param['token'], $end) === false) { + $this->throwError($phpcsFile, $param['token'], 'default', $param['content']); + } + } + + /* + * No need for the sniff to be triggered by the T_VARIABLEs in the function + * definition as we've already examined them above, so let's skip over them. + */ + return $closer; + + case 'T_VARIABLE': + case 'T_STATIC': + case 'T_CONST': + $type = 'const'; + + // Filter out non-property declarations. + if ($tokens[$stackPtr]['code'] === \T_VARIABLE) { + if ($this->isClassProperty($phpcsFile, $stackPtr) === false) { + return; + } + + $type = 'property'; + + // Move back one token to have the same starting point as the others. + $stackPtr = ($stackPtr - 1); + } + + // Filter out late static binding and class properties. + if ($tokens[$stackPtr]['code'] === \T_STATIC) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($next === false || $tokens[$next]['code'] !== \T_VARIABLE) { + // Late static binding. + return; + } + + if ($this->isClassProperty($phpcsFile, $next) === true) { + // Class properties are examined based on the T_VARIABLE token. + return; + } + unset($next); + + $type = 'staticvar'; + } + + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1)); + if ($endOfStatement === false) { + // No semi-colon - live coding. + return; + } + + $targetNestingLevel = 0; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $targetNestingLevel = \count($tokens[$stackPtr]['nested_parenthesis']); + } + + // Examine each variable/constant in multi-declarations. + $start = $stackPtr; + $end = $stackPtr; + while (($end = $phpcsFile->findNext(array(\T_COMMA, \T_SEMICOLON, \T_OPEN_SHORT_ARRAY, \T_CLOSE_TAG), ($end + 1), ($endOfStatement + 1))) !== false) { + + $maybeSkipTo = $this->isRealEndOfDeclaration($tokens, $end, $targetNestingLevel); + if ($maybeSkipTo !== true) { + $end = $maybeSkipTo; + continue; + } + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, ($start + 1), $end, true); + if ($start === false + || ($tokens[$stackPtr]['code'] === \T_CONST && $tokens[$start]['code'] !== \T_STRING) + || ($tokens[$stackPtr]['code'] !== \T_CONST && $tokens[$start]['code'] !== \T_VARIABLE) + ) { + // Shouldn't be possible. + continue; + } + + if ($this->isValidAssignment($phpcsFile, $start, $end) === false) { + // Create the "found" snippet. + $content = ''; + $tokenCount = ($end - $start); + if ($tokenCount < 20) { + // Prevent large arrays from being added to the error message. + $content = $phpcsFile->getTokensAsString($start, ($tokenCount + 1)); + } + + $this->throwError($phpcsFile, $start, $type, $content); + } + + $start = $end; + } + + // Skip to the end of the statement to prevent duplicate messages for multi-declarations. + return $endOfStatement; + } + } + + + /** + * Is a value declared and is the value declared valid pre-PHP 5.6 ? + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $end The end of the value definition. + * This will normally be a comma or semi-colon. + * + * @return bool + */ + protected function isValidAssignment(File $phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), $end, true); + if ($next === false || $tokens[$next]['code'] !== \T_EQUAL) { + // No value assigned. + return true; + } + + return $this->isStaticValue($phpcsFile, $tokens, ($next + 1), ($end - 1)); + } + + + /** + * Is a value declared and is the value declared constant as accepted in PHP 5.5 and lower ? + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $tokens The token stack of the current file. + * @param int $start The stackPtr from which to start examining. + * @param int $end The end of the value definition (inclusive), + * i.e. this token will be examined as part of + * the snippet. + * @param int $nestedArrays Optional. Array nesting level when examining + * the content of an array. + * + * @return bool + */ + protected function isStaticValue(File $phpcsFile, $tokens, $start, $end, $nestedArrays = 0) + { + $nextNonSimple = $phpcsFile->findNext($this->safeOperands, $start, ($end + 1), true); + if ($nextNonSimple === false) { + return true; + } + + /* + * OK, so we have at least one token which needs extra examination. + */ + switch ($tokens[$nextNonSimple]['code']) { + case \T_MINUS: + case \T_PLUS: + if ($this->isNumber($phpcsFile, $start, $end, true) !== false) { + // Int or float with sign. + return true; + } + + return false; + + case \T_NAMESPACE: + case \T_PARENT: + case \T_SELF: + case \T_DOUBLE_COLON: + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonSimple + 1), ($end + 1), true); + + if ($tokens[$nextNonSimple]['code'] === \T_NAMESPACE) { + // Allow only `namespace\...`. + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_NS_SEPARATOR) { + return false; + } + } elseif ($tokens[$nextNonSimple]['code'] === \T_PARENT + || $tokens[$nextNonSimple]['code'] === \T_SELF + ) { + // Allow only `parent::` and `self::`. + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_DOUBLE_COLON) { + return false; + } + } elseif ($tokens[$nextNonSimple]['code'] === \T_DOUBLE_COLON) { + // Allow only `T_STRING::T_STRING`. + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + return false; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextNonSimple - 1), null, true); + // No need to worry about parent/self, that's handled above and + // the double colon is skipped over in that case. + if ($prevNonEmpty === false || $tokens[$prevNonEmpty]['code'] !== \T_STRING) { + return false; + } + } + + // Examine what comes after the namespace/parent/self/double colon, if anything. + return $this->isStaticValue($phpcsFile, $tokens, ($nextNonEmpty + 1), $end, $nestedArrays); + + case \T_ARRAY: + case \T_OPEN_SHORT_ARRAY: + ++$nestedArrays; + + $arrayItems = $this->getFunctionCallParameters($phpcsFile, $nextNonSimple); + if (empty($arrayItems) === false) { + foreach ($arrayItems as $item) { + // Check for a double arrow, but only if it's for this array item, not for a nested array. + $doubleArrow = false; + + $maybeDoubleArrow = $phpcsFile->findNext( + array(\T_DOUBLE_ARROW, \T_ARRAY, \T_OPEN_SHORT_ARRAY), + $item['start'], + ($item['end'] + 1) + ); + if ($maybeDoubleArrow !== false && $tokens[$maybeDoubleArrow]['code'] === \T_DOUBLE_ARROW) { + // Double arrow is for this nesting level. + $doubleArrow = $maybeDoubleArrow; + } + + if ($doubleArrow === false) { + if ($this->isStaticValue($phpcsFile, $tokens, $item['start'], $item['end'], $nestedArrays) === false) { + return false; + } + + } else { + // Examine array key. + if ($this->isStaticValue($phpcsFile, $tokens, $item['start'], ($doubleArrow - 1), $nestedArrays) === false) { + return false; + } + + // Examine array value. + if ($this->isStaticValue($phpcsFile, $tokens, ($doubleArrow + 1), $item['end'], $nestedArrays) === false) { + return false; + } + } + } + } + + --$nestedArrays; + + /* + * Find the end of the array. + * We already know we will have a valid closer as otherwise we wouldn't have been + * able to get the array items. + */ + $closer = ($nextNonSimple + 1); + if ($tokens[$nextNonSimple]['code'] === \T_OPEN_SHORT_ARRAY + && isset($tokens[$nextNonSimple]['bracket_closer']) === true + ) { + $closer = $tokens[$nextNonSimple]['bracket_closer']; + } else { + $maybeOpener = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonSimple + 1), ($end + 1), true); + if ($tokens[$maybeOpener]['code'] === \T_OPEN_PARENTHESIS) { + $opener = $maybeOpener; + if (isset($tokens[$opener]['parenthesis_closer']) === true) { + $closer = $tokens[$opener]['parenthesis_closer']; + } + } + } + + if ($closer === $end) { + return true; + } + + // Examine what comes after the array, if anything. + return $this->isStaticValue($phpcsFile, $tokens, ($closer + 1), $end, $nestedArrays); + + } + + // Ok, so this unsafe token was not one of the exceptions, i.e. this is a PHP 5.6+ syntax. + return false; + } + + + /** + * Throw an error if a scalar expression is found. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the token to link the error to. + * @param string $type Type of usage found. + * @param string $content Optional. The value for the declaration as found. + * + * @return void + */ + protected function throwError(File $phpcsFile, $stackPtr, $type, $content = '') + { + $error = static::ERROR_PHRASE; + $phrase = ''; + $errorCode = 'Found'; + + if (isset($this->errorPhrases[$type]) === true) { + $errorCode = $this->stringToErrorCode($type) . 'Found'; + $phrase = $this->errorPhrases[$type]; + } + + $data = array($phrase); + + if (empty($content) === false) { + $error .= ' Found: %s'; + $data[] = $content; + } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + + + /** + * Helper function to find the end of multi variable/constant declarations. + * + * Checks whether a certain part of a declaration needs to be skipped over or + * if it is the real end of the declaration. + * + * @since 8.2.0 + * + * @param array $tokens Token stack of the current file. + * @param int $endPtr The token to examine as a candidate end pointer. + * @param int $targetLevel Target nesting level. + * + * @return bool|int True if this is the real end. Int stackPtr to skip to if not. + */ + private function isRealEndOfDeclaration($tokens, $endPtr, $targetLevel) + { + // Ignore anything within short array definition brackets for now. + if ($tokens[$endPtr]['code'] === \T_OPEN_SHORT_ARRAY + && (isset($tokens[$endPtr]['bracket_opener']) + && $tokens[$endPtr]['bracket_opener'] === $endPtr) + && isset($tokens[$endPtr]['bracket_closer']) + ) { + // Skip forward to the end of the short array definition. + return $tokens[$endPtr]['bracket_closer']; + } + + // Skip past comma's at a lower nesting level. + if ($tokens[$endPtr]['code'] === \T_COMMA) { + // Check if a comma is at the nesting level we're targetting. + $nestingLevel = 0; + if (isset($tokens[$endPtr]['nested_parenthesis']) === true) { + $nestingLevel = \count($tokens[$endPtr]['nested_parenthesis']); + } + if ($nestingLevel > $targetLevel) { + return $endPtr; + } + } + + return true; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php new file mode 100644 index 000000000..406237a50 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/InitialValue/NewHeredocSniff.php @@ -0,0 +1,100 @@ + 'constants', + 'property' => 'class properties', + 'staticvar' => 'static variables', + 'default' => 'default parameter values', + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.2') !== true); + } + + + /** + * Is a value declared and does the declared value not contain an heredoc ? + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $end The end of the value definition. + * + * @return bool True if no heredoc (or assignment) is found, false otherwise. + */ + protected function isValidAssignment(File $phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), $end, true); + if ($next === false || $tokens[$next]['code'] !== \T_EQUAL) { + // No value assigned. + return true; + } + + return ($phpcsFile->findNext(\T_START_HEREDOC, ($next + 1), $end, false, null, true) === false); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php new file mode 100644 index 000000000..e154a6035 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/InternalInterfacesSniff.php @@ -0,0 +1,103 @@ + string) + */ + protected $internalInterfaces = array( + 'Traversable' => 'shouldn\'t be implemented directly, implement the Iterator or IteratorAggregate interface instead.', + 'DateTimeInterface' => 'is intended for type hints only and is not implementable.', + 'Throwable' => 'cannot be implemented directly, extend the Exception class instead.', + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of interface names. + $this->internalInterfaces = $this->arrayKeysToLowercase($this->internalInterfaces); + + $targets = array(\T_CLASS); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $interfaces = PHPCSHelper::findImplementedInterfaceNames($phpcsFile, $stackPtr); + + if (\is_array($interfaces) === false || $interfaces === array()) { + return; + } + + foreach ($interfaces as $interface) { + $interface = ltrim($interface, '\\'); + $interfaceLc = strtolower($interface); + if (isset($this->internalInterfaces[$interfaceLc]) === true) { + $error = 'The interface %s %s'; + $errorCode = $this->stringToErrorCode($interfaceLc) . 'Found'; + $data = array( + $interface, + $this->internalInterfaces[$interfaceLc], + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php new file mode 100644 index 000000000..35c5939ba --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Interfaces/NewInterfacesSniff.php @@ -0,0 +1,362 @@ + array(string => bool)) + */ + protected $newInterfaces = array( + 'Traversable' => array( + '4.4' => false, + '5.0' => true, + ), + 'Reflector' => array( + '4.4' => false, + '5.0' => true, + ), + + 'Countable' => array( + '5.0' => false, + '5.1' => true, + ), + 'OuterIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'RecursiveIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'SeekableIterator' => array( + '5.0' => false, + '5.1' => true, + ), + 'Serializable' => array( + '5.0' => false, + '5.1' => true, + ), + 'SplObserver' => array( + '5.0' => false, + '5.1' => true, + ), + 'SplSubject' => array( + '5.0' => false, + '5.1' => true, + ), + + 'JsonSerializable' => array( + '5.3' => false, + '5.4' => true, + ), + 'SessionHandlerInterface' => array( + '5.3' => false, + '5.4' => true, + ), + + 'DateTimeInterface' => array( + '5.4' => false, + '5.5' => true, + ), + + 'SessionIdInterface' => array( + '5.5.0' => false, + '5.5.1' => true, + ), + + 'Throwable' => array( + '5.6' => false, + '7.0' => true, + ), + 'SessionUpdateTimestampHandlerInterface' => array( + '5.6' => false, + '7.0' => true, + ), + ); + + /** + * A list of methods which cannot be used in combination with particular interfaces. + * + * @since 7.0.3 + * + * @var array(string => array(string => string)) + */ + protected $unsupportedMethods = array( + 'Serializable' => array( + '__sleep' => 'https://www.php.net/serializable', + '__wakeup' => 'https://www.php.net/serializable', + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.3 + * + * @return array + */ + public function register() + { + // Handle case-insensitivity of interface names. + $this->newInterfaces = $this->arrayKeysToLowercase($this->newInterfaces); + $this->unsupportedMethods = $this->arrayKeysToLowercase($this->unsupportedMethods); + + $targets = array( + \T_CLASS, + \T_FUNCTION, + \T_CLOSURE, + ); + + if (\defined('T_ANON_CLASS')) { + $targets[] = \T_ANON_CLASS; + } + + if (\defined('T_RETURN_TYPE')) { + $targets[] = \T_RETURN_TYPE; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + case 'T_CLASS': + case 'T_ANON_CLASS': + $this->processClassToken($phpcsFile, $stackPtr); + break; + + case 'T_FUNCTION': + case 'T_CLOSURE': + $this->processFunctionToken($phpcsFile, $stackPtr); + + // Deal with older PHPCS versions which don't recognize return type hints + // as well as newer PHPCS versions (3.3.0+) where the tokenization has changed. + $returnTypeHint = $this->getReturnTypeHintToken($phpcsFile, $stackPtr); + if ($returnTypeHint !== false) { + $this->processReturnTypeToken($phpcsFile, $returnTypeHint); + } + break; + + case 'T_RETURN_TYPE': + $this->processReturnTypeToken($phpcsFile, $stackPtr); + break; + + default: + // Deliberately left empty. + break; + } + } + + + /** + * Processes this test for when a class token is encountered. + * + * - Detect classes implementing the new interfaces. + * - Detect classes implementing the new interfaces with unsupported functions. + * + * @since 7.1.4 Split off from the `process()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processClassToken(File $phpcsFile, $stackPtr) + { + $interfaces = PHPCSHelper::findImplementedInterfaceNames($phpcsFile, $stackPtr); + + if (\is_array($interfaces) === false || $interfaces === array()) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $checkMethods = false; + + if (isset($tokens[$stackPtr]['scope_closer'])) { + $checkMethods = true; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + } + + foreach ($interfaces as $interface) { + $interface = ltrim($interface, '\\'); + $interfaceLc = strtolower($interface); + + if (isset($this->newInterfaces[$interfaceLc]) === true) { + $itemInfo = array( + 'name' => $interface, + 'nameLc' => $interfaceLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + if ($checkMethods === true && isset($this->unsupportedMethods[$interfaceLc]) === true) { + $nextFunc = $stackPtr; + while (($nextFunc = $phpcsFile->findNext(\T_FUNCTION, ($nextFunc + 1), $scopeCloser)) !== false) { + $funcName = $phpcsFile->getDeclarationName($nextFunc); + $funcNameLc = strtolower($funcName); + if ($funcNameLc === '') { + continue; + } + + if (isset($this->unsupportedMethods[$interfaceLc][$funcNameLc]) === true) { + $error = 'Classes that implement interface %s do not support the method %s(). See %s'; + $errorCode = $this->stringToErrorCode($interface) . 'UnsupportedMethod'; + $data = array( + $interface, + $funcName, + $this->unsupportedMethods[$interfaceLc][$funcNameLc], + ); + + $phpcsFile->addError($error, $nextFunc, $errorCode, $data); + } + } + } + } + } + + + /** + * Processes this test for when a function token is encountered. + * + * - Detect new interfaces when used as a type hint. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processFunctionToken(File $phpcsFile, $stackPtr) + { + $typeHints = $this->getTypeHintsFromFunctionDeclaration($phpcsFile, $stackPtr); + if (empty($typeHints) || \is_array($typeHints) === false) { + return; + } + + foreach ($typeHints as $hint) { + + $typeHintLc = strtolower($hint); + + if (isset($this->newInterfaces[$typeHintLc]) === true) { + $itemInfo = array( + 'name' => $hint, + 'nameLc' => $typeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + } + + + /** + * Processes this test for when a return type token is encountered. + * + * - Detect new interfaces when used as a return type declaration. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + private function processReturnTypeToken(File $phpcsFile, $stackPtr) + { + $returnTypeHint = $this->getReturnTypeHintName($phpcsFile, $stackPtr); + if (empty($returnTypeHint)) { + return; + } + + $returnTypeHint = ltrim($returnTypeHint, '\\'); + $returnTypeHintLc = strtolower($returnTypeHint); + + if (isset($this->newInterfaces[$returnTypeHintLc]) === false) { + return; + } + + // Still here ? Then this is a return type declaration using a new interface. + $itemInfo = array( + 'name' => $returnTypeHint, + 'nameLc' => $returnTypeHintLc, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newInterfaces[$itemInfo['nameLc']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The built-in interface ' . parent::getErrorMsgTemplate(); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php new file mode 100644 index 000000000..64002b4d1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/CaseSensitiveKeywordsSniff.php @@ -0,0 +1,76 @@ +supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $tokenContentLC = strtolower($tokens[$stackPtr]['content']); + + if ($tokenContentLC !== $tokens[$stackPtr]['content']) { + $phpcsFile->addError( + 'The keyword \'%s\' was treated in a case-sensitive fashion in certain cases in PHP 5.4 or earlier. Use the lowercase version for consistent support.', + $stackPtr, + 'NonLowercaseFound', + array($tokenContentLC) + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php new file mode 100644 index 000000000..7f4411bc2 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsDeclaredSniff.php @@ -0,0 +1,259 @@ + '7.0', + \T_TRUE => '7.0', + \T_FALSE => '7.0', + ); + + /** + * T_STRING keywords to recognize as forbidden names. + * + * @since 7.0.8 + * + * @var array + */ + protected $forbiddenNames = array( + 'null' => '7.0', + 'true' => '7.0', + 'false' => '7.0', + 'bool' => '7.0', + 'int' => '7.0', + 'float' => '7.0', + 'string' => '7.0', + 'iterable' => '7.1', + 'void' => '7.1', + 'object' => '7.2', + ); + + /** + * T_STRING keywords to recognize as soft reserved names. + * + * Using any of these keywords to name a class, interface, trait or namespace + * is highly discouraged since they may be used in future versions of PHP. + * + * @since 7.0.8 + * + * @var array + */ + protected $softReservedNames = array( + 'resource' => '7.0', + 'object' => '7.0', + 'mixed' => '7.0', + 'numeric' => '7.0', + ); + + /** + * Combined list of the two lists above. + * + * Used for quick check whether or not something is a reserved + * word. + * Set from the `register()` method. + * + * @since 7.0.8 + * + * @var array + */ + private $allForbiddenNames = array(); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.8 + * + * @return array + */ + public function register() + { + // Do the list merge only once. + $this->allForbiddenNames = array_merge($this->forbiddenNames, $this->softReservedNames); + + $targets = array( + \T_CLASS, + \T_INTERFACE, + \T_TRAIT, + \T_NAMESPACE, + \T_STRING, // Compat for PHPCS < 2.4.0 and PHP < 5.3. + ); + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.8 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + $tokenType = $tokens[$stackPtr]['type']; + $tokenContentLc = strtolower($tokens[$stackPtr]['content']); + + // For string tokens we only care about 'trait' as that is the only one + // which may not be correctly recognized as it's own token. + // This only happens in older versions of PHP where the token doesn't exist yet as a keyword. + if ($tokenCode === \T_STRING && $tokenContentLc !== 'trait') { + return; + } + + if (\in_array($tokenType, array('T_CLASS', 'T_INTERFACE', 'T_TRAIT'), true)) { + // Check for the declared name being a name which is not tokenized as T_STRING. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== false && isset($this->forbiddenTokens[$tokens[$nextNonEmpty]['code']]) === true) { + $name = $tokens[$nextNonEmpty]['content']; + } else { + // Get the declared name if it's a T_STRING. + $name = $phpcsFile->getDeclarationName($stackPtr); + } + unset($nextNonEmpty); + + if (isset($name) === false || \is_string($name) === false || $name === '') { + return; + } + + $nameLc = strtolower($name); + if (isset($this->allForbiddenNames[$nameLc]) === false) { + return; + } + + } elseif ($tokenCode === \T_NAMESPACE) { + $namespaceName = $this->getDeclaredNamespaceName($phpcsFile, $stackPtr); + + if ($namespaceName === false || $namespaceName === '') { + return; + } + + $namespaceParts = explode('\\', $namespaceName); + foreach ($namespaceParts as $namespacePart) { + $partLc = strtolower($namespacePart); + if (isset($this->allForbiddenNames[$partLc]) === true) { + $name = $namespacePart; + $nameLc = $partLc; + break; + } + } + } elseif ($tokenCode === \T_STRING) { + // Traits which are not yet tokenized as T_TRAIT. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + $nextNonEmptyCode = $tokens[$nextNonEmpty]['code']; + + if ($nextNonEmptyCode !== \T_STRING && isset($this->forbiddenTokens[$nextNonEmptyCode]) === true) { + $name = $tokens[$nextNonEmpty]['content']; + $nameLc = strtolower($tokens[$nextNonEmpty]['content']); + } elseif ($nextNonEmptyCode === \T_STRING) { + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_OPEN_CURLY_BRACKET), ($stackPtr + 1)); + if ($endOfStatement === false) { + return; + } + + do { + $nextNonEmptyLc = strtolower($tokens[$nextNonEmpty]['content']); + + if (isset($this->allForbiddenNames[$nextNonEmptyLc]) === true) { + $name = $tokens[$nextNonEmpty]['content']; + $nameLc = $nextNonEmptyLc; + break; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), $endOfStatement, true); + } while ($nextNonEmpty !== false); + } + unset($nextNonEmptyCode, $nextNonEmptyLc, $endOfStatement); + } + + if (isset($name, $nameLc) === false) { + return; + } + + // Still here, so this is one of the reserved words. + // Build up the error message. + $error = "'%s' is a"; + $isError = null; + $errorCode = $this->stringToErrorCode($nameLc) . 'Found'; + $data = array( + $nameLc, + ); + + if (isset($this->softReservedNames[$nameLc]) === true + && $this->supportsAbove($this->softReservedNames[$nameLc]) === true + ) { + $error .= ' soft reserved keyword as of PHP version %s'; + $isError = false; + $data[] = $this->softReservedNames[$nameLc]; + } + + if (isset($this->forbiddenNames[$nameLc]) === true + && $this->supportsAbove($this->forbiddenNames[$nameLc]) === true + ) { + if (isset($isError) === true) { + $error .= ' and a'; + } + $error .= ' reserved keyword as of PHP version %s'; + $isError = true; + $data[] = $this->forbiddenNames[$nameLc]; + } + + if (isset($isError) === true) { + $error .= ' and should not be used to name a class, interface or trait or as part of a namespace (%s)'; + $data[] = $tokens[$stackPtr]['type']; + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php new file mode 100644 index 000000000..c1c382812 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesAsInvokedFunctionsSniff.php @@ -0,0 +1,188 @@ + '5.0', + \T_CALLABLE => '5.4', + \T_CATCH => '5.0', + \T_FINAL => '5.0', + \T_FINALLY => '5.5', + \T_GOTO => '5.3', + \T_IMPLEMENTS => '5.0', + \T_INTERFACE => '5.0', + \T_INSTANCEOF => '5.0', + \T_INSTEADOF => '5.4', + \T_NAMESPACE => '5.3', + \T_PRIVATE => '5.0', + \T_PROTECTED => '5.0', + \T_PUBLIC => '5.0', + \T_TRAIT => '5.4', + \T_TRY => '5.0', + + ); + + /** + * T_STRING keywords to recognize as targetted tokens. + * + * Compatibility for PHP versions where the keyword is not yet recognized + * as its own token and for PHPCS versions which change the token to + * T_STRING when used in a method call. + * + * @since 5.5 + * + * @var array + */ + protected $targetedStringTokens = array( + 'abstract' => '5.0', + 'callable' => '5.4', + 'catch' => '5.0', + 'final' => '5.0', + 'finally' => '5.5', + 'goto' => '5.3', + 'implements' => '5.0', + 'interface' => '5.0', + 'instanceof' => '5.0', + 'insteadof' => '5.4', + 'namespace' => '5.3', + 'private' => '5.0', + 'protected' => '5.0', + 'public' => '5.0', + 'trait' => '5.4', + 'try' => '5.0', + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + $tokens = array_keys($this->targetedTokens); + $tokens[] = \T_STRING; + + return $tokens; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenCode = $tokens[$stackPtr]['code']; + $tokenContentLc = strtolower($tokens[$stackPtr]['content']); + $isString = false; + + /* + * For string tokens we only care if the string is a reserved word used + * as a function. This only happens in older versions of PHP where the + * token doesn't exist yet for that keyword or in later versions when the + * token is used in a method invocation. + */ + if ($tokenCode === \T_STRING + && (isset($this->targetedStringTokens[$tokenContentLc]) === false) + ) { + return; + } + + if ($tokenCode === \T_STRING) { + $isString = true; + } + + // Make sure this is a function call. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + // This sniff isn't concerned about function declarations. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['code'] === \T_FUNCTION) { + return; + } + + /* + * Deal with PHP 7 relaxing the rules. + * "As of PHP 7.0.0 these keywords are allowed as property, constant, and method names + * of classes, interfaces and traits...", i.e. they can be invoked as a method call. + * + * Only needed for those keywords which we sniff out via T_STRING. + */ + if (($tokens[$prev]['code'] === \T_OBJECT_OPERATOR || $tokens[$prev]['code'] === \T_DOUBLE_COLON) + && $this->supportsBelow('5.6') === false + ) { + return; + } + + // For the word catch, it is valid to have an open parenthesis + // after it, but only if it is preceded by a right curly brace. + if ($tokenCode === \T_CATCH) { + if ($prev !== false && $tokens[$prev]['code'] === \T_CLOSE_CURLY_BRACKET) { + // Ok, it's fine. + return; + } + } + + if ($isString === true) { + $version = $this->targetedStringTokens[$tokenContentLc]; + } else { + $version = $this->targetedTokens[$tokenCode]; + } + + if ($this->supportsAbove($version)) { + $error = "'%s' is a reserved keyword introduced in PHP version %s and cannot be invoked as a function (%s)"; + $errorCode = $this->stringToErrorCode($tokenContentLc) . 'Found'; + $data = array( + $tokenContentLc, + $version, + $tokens[$stackPtr]['type'], + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php new file mode 100644 index 000000000..6be1de4f1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/ForbiddenNamesSniff.php @@ -0,0 +1,442 @@ + string) + */ + protected $invalidNames = array( + 'abstract' => '5.0', + 'and' => 'all', + 'array' => 'all', + 'as' => 'all', + 'break' => 'all', + 'callable' => '5.4', + 'case' => 'all', + 'catch' => '5.0', + 'class' => 'all', + 'clone' => '5.0', + 'const' => 'all', + 'continue' => 'all', + 'declare' => 'all', + 'default' => 'all', + 'die' => 'all', + 'do' => 'all', + 'echo' => 'all', + 'else' => 'all', + 'elseif' => 'all', + 'empty' => 'all', + 'enddeclare' => 'all', + 'endfor' => 'all', + 'endforeach' => 'all', + 'endif' => 'all', + 'endswitch' => 'all', + 'endwhile' => 'all', + 'eval' => 'all', + 'exit' => 'all', + 'extends' => 'all', + 'final' => '5.0', + 'finally' => '5.5', + 'for' => 'all', + 'foreach' => 'all', + 'function' => 'all', + 'global' => 'all', + 'goto' => '5.3', + 'if' => 'all', + 'implements' => '5.0', + 'include' => 'all', + 'include_once' => 'all', + 'instanceof' => '5.0', + 'insteadof' => '5.4', + 'interface' => '5.0', + 'isset' => 'all', + 'list' => 'all', + 'namespace' => '5.3', + 'new' => 'all', + 'or' => 'all', + 'print' => 'all', + 'private' => '5.0', + 'protected' => '5.0', + 'public' => '5.0', + 'require' => 'all', + 'require_once' => 'all', + 'return' => 'all', + 'static' => 'all', + 'switch' => 'all', + 'throw' => '5.0', + 'trait' => '5.4', + 'try' => '5.0', + 'unset' => 'all', + 'use' => 'all', + 'var' => 'all', + 'while' => 'all', + 'xor' => 'all', + 'yield' => '5.5', + '__class__' => 'all', + '__dir__' => '5.3', + '__file__' => 'all', + '__function__' => 'all', + '__method__' => 'all', + '__namespace__' => '5.3', + ); + + /** + * A list of keywords that can follow use statements. + * + * @since 7.0.1 + * + * @var array(string => string) + */ + protected $validUseNames = array( + 'const' => true, + 'function' => true, + ); + + /** + * Scope modifiers and other keywords allowed in trait use statements. + * + * @since 7.1.4 + * + * @var array + */ + private $allowedModifiers = array(); + + /** + * Targeted tokens. + * + * @since 5.5 + * + * @var array + */ + protected $targetedTokens = array( + \T_CLASS, + \T_FUNCTION, + \T_NAMESPACE, + \T_STRING, + \T_CONST, + \T_USE, + \T_AS, + \T_EXTENDS, + \T_INTERFACE, + \T_TRAIT, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + $this->allowedModifiers = Tokens::$scopeModifiers; + $this->allowedModifiers[\T_FINAL] = \T_FINAL; + + $tokens = $this->targetedTokens; + + if (\defined('T_ANON_CLASS')) { + $tokens[] = \T_ANON_CLASS; + } + + return $tokens; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + /* + * We distinguish between the class, function and namespace names vs the define statements. + */ + if ($tokens[$stackPtr]['type'] === 'T_STRING') { + $this->processString($phpcsFile, $stackPtr, $tokens); + } else { + $this->processNonString($phpcsFile, $stackPtr, $tokens); + } + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processNonString(File $phpcsFile, $stackPtr, $tokens) + { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + /* + * Deal with anonymous classes - `class` before a reserved keyword is sometimes + * misidentified as `T_ANON_CLASS`. + * In PHPCS < 2.3.4 these were tokenized as T_CLASS no matter what. + */ + if ($tokens[$stackPtr]['type'] === 'T_ANON_CLASS' || $tokens[$stackPtr]['type'] === 'T_CLASS') { + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevNonEmpty !== false && $tokens[$prevNonEmpty]['type'] === 'T_NEW') { + return; + } + } + + /* + * PHP 5.6 allows for use const and use function, but only if followed by the function/constant name. + * - `use function HelloWorld` => move to the next token (HelloWorld) to verify. + * - `use const HelloWorld` => move to the next token (HelloWorld) to verify. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_USE' + && isset($this->validUseNames[strtolower($tokens[$nextNonEmpty]['content'])]) === true + ) { + $maybeUseNext = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true, null, true); + if ($maybeUseNext !== false && $this->isEndOfUseStatement($tokens[$maybeUseNext]) === false) { + $nextNonEmpty = $maybeUseNext; + } + } + + /* + * Deal with visibility modifiers. + * - `use HelloWorld { sayHello as protected; }` => valid, bow out. + * - `use HelloWorld { sayHello as private myPrivateHello; }` => move to the next token to verify. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_AS' + && isset($this->allowedModifiers[$tokens[$nextNonEmpty]['code']]) === true + && $phpcsFile->hasCondition($stackPtr, \T_USE) === true + ) { + $maybeUseNext = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true, null, true); + if ($maybeUseNext === false || $this->isEndOfUseStatement($tokens[$maybeUseNext]) === true) { + return; + } + + $nextNonEmpty = $maybeUseNext; + } + + /* + * Deal with foreach ( ... as list() ). + */ + elseif ($tokens[$stackPtr]['type'] === 'T_AS' + && isset($tokens[$stackPtr]['nested_parenthesis']) === true + && $tokens[$nextNonEmpty]['code'] === \T_LIST + ) { + $parentheses = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true); + foreach ($parentheses as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) + && $tokens[$tokens[$open]['parenthesis_owner']]['code'] === \T_FOREACH + ) { + return; + } + } + } + + /* + * Deal with functions declared to return by reference. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_FUNCTION' + && $tokens[$nextNonEmpty]['type'] === 'T_BITWISE_AND' + ) { + $maybeUseNext = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true, null, true); + if ($maybeUseNext === false) { + // Live coding. + return; + } + + $nextNonEmpty = $maybeUseNext; + } + + /* + * Deal with nested namespaces. + */ + elseif ($tokens[$stackPtr]['type'] === 'T_NAMESPACE') { + if ($tokens[$stackPtr + 1]['code'] === \T_NS_SEPARATOR) { + // Not a namespace declaration, but use of, i.e. `namespace\someFunction();`. + return; + } + + $endToken = $phpcsFile->findNext(array(\T_SEMICOLON, \T_OPEN_CURLY_BRACKET), ($stackPtr + 1), null, false, null, true); + $namespaceName = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($endToken - $stackPtr - 1))); + if (empty($namespaceName) === true) { + return; + } + + $namespaceParts = explode('\\', $namespaceName); + foreach ($namespaceParts as $namespacePart) { + $partLc = strtolower($namespacePart); + if (isset($this->invalidNames[$partLc]) === false) { + continue; + } + + // Find the token position of the part which matched. + for ($i = ($stackPtr + 1); $i < $endToken; $i++) { + if ($tokens[$i]['content'] === $namespacePart) { + $nextNonEmpty = $i; + break; + } + } + } + unset($i, $namespacePart, $partLc); + } + + $nextContentLc = strtolower($tokens[$nextNonEmpty]['content']); + if (isset($this->invalidNames[$nextContentLc]) === false) { + return; + } + + /* + * Deal with PHP 7 relaxing the rules. + * "As of PHP 7.0.0 these keywords are allowed as property, constant, and method names + * of classes, interfaces and traits, except that class may not be used as constant name." + */ + if ((($tokens[$stackPtr]['type'] === 'T_FUNCTION' + && $this->inClassScope($phpcsFile, $stackPtr, false) === true) + || ($tokens[$stackPtr]['type'] === 'T_CONST' + && $this->isClassConstant($phpcsFile, $stackPtr) === true + && $nextContentLc !== 'class')) + && $this->supportsBelow('5.6') === false + ) { + return; + } + + if ($this->supportsAbove($this->invalidNames[$nextContentLc])) { + $data = array( + $tokens[$nextNonEmpty]['content'], + $this->invalidNames[$nextContentLc], + ); + $this->addError($phpcsFile, $stackPtr, $tokens[$nextNonEmpty]['content'], $data); + } + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processString(File $phpcsFile, $stackPtr, $tokens) + { + $tokenContentLc = strtolower($tokens[$stackPtr]['content']); + + /* + * Special case for PHP versions where the target is not yet identified as + * its own token, but presents as T_STRING. + * - trait keyword in PHP < 5.4 + */ + if (version_compare(\PHP_VERSION_ID, '50400', '<') && $tokenContentLc === 'trait') { + $this->processNonString($phpcsFile, $stackPtr, $tokens); + return; + } + + // Look for any define/defined tokens (both T_STRING ones, blame Tokenizer). + if ($tokenContentLc !== 'define' && $tokenContentLc !== 'defined') { + return; + } + + // Retrieve the define(d) constant name. + $firstParam = $this->getFunctionCallParameter($phpcsFile, $stackPtr, 1); + if ($firstParam === false) { + return; + } + + $defineName = $this->stripQuotes($firstParam['raw']); + $defineNameLc = strtolower($defineName); + + if (isset($this->invalidNames[$defineNameLc]) && $this->supportsAbove($this->invalidNames[$defineNameLc])) { + $data = array( + $defineName, + $this->invalidNames[$defineNameLc], + ); + $this->addError($phpcsFile, $stackPtr, $defineNameLc, $data); + } + } + + + /** + * Add the error message. + * + * @since 7.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $content The token content found. + * @param array $data The data to pass into the error message. + * + * @return void + */ + protected function addError(File $phpcsFile, $stackPtr, $content, $data) + { + $error = "Function name, class name, namespace name or constant name can not be reserved keyword '%s' (since version %s)"; + $errorCode = $this->stringToErrorCode($content) . 'Found'; + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + + + /** + * Check if the current token code is for a token which can be considered + * the end of a (partial) use statement. + * + * @since 7.0.8 + * + * @param int $token The current token information. + * + * @return bool + */ + protected function isEndOfUseStatement($token) + { + return \in_array($token['code'], array(\T_CLOSE_CURLY_BRACKET, \T_SEMICOLON, \T_COMMA), true); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php new file mode 100644 index 000000000..61f79aa56 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Keywords/NewKeywordsSniff.php @@ -0,0 +1,391 @@ + array(string => bool|string)) + */ + protected $newKeywords = array( + 'T_HALT_COMPILER' => array( + '5.0' => false, + '5.1' => true, + 'description' => '"__halt_compiler" keyword', + ), + 'T_CONST' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"const" keyword', + 'condition' => 'isClassConstant', // Keyword is only new when not in class context. + ), + 'T_CALLABLE' => array( + '5.3' => false, + '5.4' => true, + 'description' => '"callable" keyword', + 'content' => 'callable', + ), + 'T_DIR' => array( + '5.2' => false, + '5.3' => true, + 'description' => '__DIR__ magic constant', + 'content' => '__DIR__', + ), + 'T_GOTO' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"goto" keyword', + 'content' => 'goto', + ), + 'T_INSTEADOF' => array( + '5.3' => false, + '5.4' => true, + 'description' => '"insteadof" keyword (for traits)', + 'content' => 'insteadof', + ), + 'T_NAMESPACE' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"namespace" keyword', + 'content' => 'namespace', + ), + 'T_NS_C' => array( + '5.2' => false, + '5.3' => true, + 'description' => '__NAMESPACE__ magic constant', + 'content' => '__NAMESPACE__', + ), + 'T_USE' => array( + '5.2' => false, + '5.3' => true, + 'description' => '"use" keyword (for traits/namespaces/anonymous functions)', + ), + 'T_START_NOWDOC' => array( + '5.2' => false, + '5.3' => true, + 'description' => 'nowdoc functionality', + ), + 'T_END_NOWDOC' => array( + '5.2' => false, + '5.3' => true, + 'description' => 'nowdoc functionality', + ), + 'T_START_HEREDOC' => array( + '5.2' => false, + '5.3' => true, + 'description' => '(Double) quoted Heredoc identifier', + 'condition' => 'isNotQuoted', // Heredoc is only new with quoted identifier. + ), + 'T_TRAIT' => array( + '5.3' => false, + '5.4' => true, + 'description' => '"trait" keyword', + 'content' => 'trait', + ), + 'T_TRAIT_C' => array( + '5.3' => false, + '5.4' => true, + 'description' => '__TRAIT__ magic constant', + 'content' => '__TRAIT__', + ), + // The specifics for distinguishing between 'yield' and 'yield from' are dealt + // with in the translation logic. + // This token has to be placed above the `T_YIELD` token in this array to allow for this. + 'T_YIELD_FROM' => array( + '5.6' => false, + '7.0' => true, + 'description' => '"yield from" keyword (for generators)', + 'content' => 'yield', + ), + 'T_YIELD' => array( + '5.4' => false, + '5.5' => true, + 'description' => '"yield" keyword (for generators)', + 'content' => 'yield', + ), + 'T_FINALLY' => array( + '5.4' => false, + '5.5' => true, + 'description' => '"finally" keyword (in exception handling)', + 'content' => 'finally', + ), + ); + + /** + * Translation table for T_STRING tokens. + * + * Will be set up from the register() method. + * + * @since 7.0.5 + * + * @var array(string => string) + */ + protected $translateContentToToken = array(); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + $tokens = array(); + $translate = array(); + foreach ($this->newKeywords as $token => $versions) { + if (\defined($token)) { + $tokens[] = constant($token); + } + if (isset($versions['content'])) { + $translate[strtolower($versions['content'])] = $token; + } + } + + /* + * Deal with tokens not recognized by the PHP version the sniffer is run + * under and (not correctly) compensated for by PHPCS. + */ + if (empty($translate) === false) { + $this->translateContentToToken = $translate; + $tokens[] = \T_STRING; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Allow for dealing with multi-token keywords, like "yield from". + $end = $stackPtr; + + // Translate T_STRING token if necessary. + if ($tokens[$stackPtr]['type'] === 'T_STRING') { + $content = strtolower($tokens[$stackPtr]['content']); + + if (isset($this->translateContentToToken[$content]) === false) { + // Not one of the tokens we're looking for. + return; + } + + $tokenType = $this->translateContentToToken[$content]; + } + + /* + * Special case: distinguish between `yield` and `yield from`. + * + * PHPCS currently (at least up to v 3.0.1) does not backfill for the + * `yield` nor the `yield from` keywords. + * See: https://github.com/squizlabs/PHP_CodeSniffer/issues/1524 + * + * In PHP < 5.5, both `yield` as well as `from` are tokenized as T_STRING. + * In PHP 5.5 - 5.6, `yield` is tokenized as T_YIELD and `from` as T_STRING, + * but the `T_YIELD_FROM` token *is* defined in PHP. + * In PHP 7.0+ both are tokenized as their respective token, however, + * a multi-line "yield from" is tokenized as two tokens. + */ + if ($tokenType === 'T_YIELD') { + $nextToken = $phpcsFile->findNext(\T_WHITESPACE, ($end + 1), null, true); + if ($tokens[$nextToken]['code'] === \T_STRING + && $tokens[$nextToken]['content'] === 'from' + ) { + $tokenType = 'T_YIELD_FROM'; + $end = $nextToken; + } + unset($nextToken); + } + + if ($tokenType === 'T_YIELD_FROM' && $tokens[($stackPtr - 1)]['type'] === 'T_YIELD_FROM') { + // Multi-line "yield from", no need to report it twice. + return; + } + + if (isset($this->newKeywords[$tokenType]) === false) { + return; + } + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($prevToken !== false + && ($tokens[$prevToken]['code'] === \T_DOUBLE_COLON + || $tokens[$prevToken]['code'] === \T_OBJECT_OPERATOR) + ) { + // Class property of the same name as one of the keywords. Ignore. + return; + } + + // Skip attempts to use keywords as functions or class names - the former + // will be reported by ForbiddenNamesAsInvokedFunctionsSniff, whilst the + // latter will be (partially) reported by the ForbiddenNames sniff. + // Either type will result in false-positives when targetting lower versions + // of PHP where the name was not reserved, unless we explicitly check for + // them. + if (($nextToken === false + || $tokens[$nextToken]['type'] !== 'T_OPEN_PARENTHESIS') + && ($prevToken === false + || $tokens[$prevToken]['type'] !== 'T_CLASS' + || $tokens[$prevToken]['type'] !== 'T_INTERFACE') + ) { + // Skip based on token scope condition. + if (isset($this->newKeywords[$tokenType]['condition']) + && \call_user_func(array($this, $this->newKeywords[$tokenType]['condition']), $phpcsFile, $stackPtr) === true + ) { + return; + } + + $itemInfo = array( + 'name' => $tokenType, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newKeywords[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array( + 'description', + 'condition', + 'content', + ); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + return $data; + } + + + /** + * Callback for the quoted heredoc identifier condition. + * + * A double quoted identifier will have the opening quote on position 3 + * in the string: `<<<"ID"`. + * + * @since 8.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return bool + */ + public function isNotQuoted(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + return ($tokens[$stackPtr]['content'][3] !== '"'); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php new file mode 100644 index 000000000..ffb9ef281 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewEmptyNonVariableSniff.php @@ -0,0 +1,91 @@ +supportsBelow('5.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $open = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($open === false + || $tokens[$open]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$open]['parenthesis_closer']) === false + ) { + return; + } + + $close = $tokens[$open]['parenthesis_closer']; + + $nestingLevel = 0; + if ($close !== ($open + 1) && isset($tokens[$open + 1]['nested_parenthesis'])) { + $nestingLevel = \count($tokens[$open + 1]['nested_parenthesis']); + } + + if ($this->isVariable($phpcsFile, ($open + 1), $close, $nestingLevel) === true) { + return; + } + + $phpcsFile->addError( + 'Only variables can be passed to empty() prior to PHP 5.5.', + $stackPtr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php new file mode 100644 index 000000000..44488ed0a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/LanguageConstructs/NewLanguageConstructsSniff.php @@ -0,0 +1,159 @@ + array(string => bool|string)) + */ + protected $newConstructs = array( + 'T_NS_SEPARATOR' => array( + '5.2' => false, + '5.3' => true, + 'description' => 'the \ operator (for namespaces)', + ), + 'T_ELLIPSIS' => array( + '5.5' => false, + '5.6' => true, + 'description' => 'the ... spread operator', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->newConstructs as $token => $versions) { + $tokens[] = constant($token); + } + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.6 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + $itemInfo = array( + 'name' => $tokenType, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newConstructs[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Allow for concrete child classes to filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + return $data; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php new file mode 100644 index 000000000..f5ba4772f --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/AssignmentOrderSniff.php @@ -0,0 +1,188 @@ +supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY + && $this->isShortList($phpcsFile, $stackPtr) === false + ) { + // Short array, not short list. + return; + } + + if ($tokens[$stackPtr]['code'] === \T_LIST) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false + || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false + ) { + // Parse error or live coding. + return; + } + + $opener = $nextNonEmpty; + $closer = $tokens[$nextNonEmpty]['parenthesis_closer']; + } else { + // Short list syntax. + $opener = $stackPtr; + + if (isset($tokens[$stackPtr]['bracket_closer'])) { + $closer = $tokens[$stackPtr]['bracket_closer']; + } + } + + if (isset($opener, $closer) === false) { + return; + } + + /* + * OK, so we have the opener & closer, now we need to check all the variables in the + * list() to see if there are duplicates as that's the problem. + */ + $hasVars = $phpcsFile->findNext(array(\T_VARIABLE, \T_DOLLAR), ($opener + 1), $closer); + if ($hasVars === false) { + // Empty list, not our concern. + return ($closer + 1); + } + + // Set the variable delimiters based on the list type being examined. + $stopPoints = array(\T_COMMA); + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + $stopPoints[] = \T_CLOSE_SHORT_ARRAY; + } else { + $stopPoints[] = \T_CLOSE_PARENTHESIS; + } + + $listVars = array(); + $lastStopPoint = $opener; + + /* + * Create a list of all variables used within the `list()` construct. + * We're not concerned with whether these are nested or not, as any duplicate + * variable name used will be problematic, independent of nesting. + */ + do { + $nextStopPoint = $phpcsFile->findNext($stopPoints, ($lastStopPoint + 1), $closer); + if ($nextStopPoint === false) { + $nextStopPoint = $closer; + } + + // Also detect this in PHP 7.1 keyed lists. + $hasDoubleArrow = $phpcsFile->findNext(\T_DOUBLE_ARROW, ($lastStopPoint + 1), $nextStopPoint); + if ($hasDoubleArrow !== false) { + $lastStopPoint = $hasDoubleArrow; + } + + // Find the start of the variable, allowing for variable variables. + $nextStartPoint = $phpcsFile->findNext(array(\T_VARIABLE, \T_DOLLAR), ($lastStopPoint + 1), $nextStopPoint); + if ($nextStartPoint === false) { + // Skip past empty bits in the list, i.e. `list( $a, , ,)`. + $lastStopPoint = $nextStopPoint; + continue; + } + + /* + * Gather the content of all non-empty tokens to determine the "variable name". + * Variable name in this context includes array or object property syntaxes, such + * as `$a['name']` and `$b->property`. + */ + $varContent = ''; + + for ($i = $nextStartPoint; $i < $nextStopPoint; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']])) { + continue; + } + + $varContent .= $tokens[$i]['content']; + } + + if ($varContent !== '') { + $listVars[] = $varContent; + } + + $lastStopPoint = $nextStopPoint; + + } while ($lastStopPoint < $closer); + + if (empty($listVars)) { + // Shouldn't be possible, but just in case. + return ($closer + 1); + } + + // Verify that all variables used in the list() construct are unique. + if (\count($listVars) !== \count(array_unique($listVars))) { + $phpcsFile->addError( + 'list() will assign variable from left-to-right since PHP 7.0. Ensure all variables in list() are unique to prevent unexpected results.', + $stackPtr, + 'Affected' + ); + } + + return ($closer + 1); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php new file mode 100644 index 000000000..b9d4b7b06 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/ForbiddenEmptyListAssignmentSniff.php @@ -0,0 +1,116 @@ +ignoreTokens = Tokens::$emptyTokens; + $this->ignoreTokens[\T_COMMA] = \T_COMMA; + $this->ignoreTokens[\T_OPEN_PARENTHESIS] = \T_OPEN_PARENTHESIS; + $this->ignoreTokens[\T_CLOSE_PARENTHESIS] = \T_CLOSE_PARENTHESIS; + + return array( + \T_LIST, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY) { + if ($this->isShortList($phpcsFile, $stackPtr) === false) { + return; + } + + $open = $stackPtr; + $close = $tokens[$stackPtr]['bracket_closer']; + } else { + // T_LIST. + $open = $phpcsFile->findNext(\T_OPEN_PARENTHESIS, $stackPtr, null, false, null, true); + if ($open === false || isset($tokens[$open]['parenthesis_closer']) === false) { + return; + } + + $close = $tokens[$open]['parenthesis_closer']; + } + + $error = true; + if (($close - $open) > 1) { + for ($cnt = $open + 1; $cnt < $close; $cnt++) { + if (isset($this->ignoreTokens[$tokens[$cnt]['code']]) === false) { + $error = false; + break; + } + } + } + + if ($error === true) { + $phpcsFile->addError( + 'Empty list() assignments are not allowed since PHP 7.0', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php new file mode 100644 index 000000000..7111b125f --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewKeyedListSniff.php @@ -0,0 +1,227 @@ + \T_LIST, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + + /** + * The token(s) within the list construct which is being targeted. + * + * @since 9.0.0 + * + * @var array + */ + protected $targetsInList = array( + \T_DOUBLE_ARROW => \T_DOUBLE_ARROW, + ); + + /** + * All tokens needed to walk through the list construct and + * determine whether the target token is contained within. + * + * Set by the setUpAllTargets() method which is called from within register(). + * + * @since 9.0.0 + * + * @var array + */ + protected $allTargets; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.0.0 + * + * @return array + */ + public function register() + { + $this->setUpAllTargets(); + + return $this->sniffTargets; + } + + /** + * Prepare the $allTargets array only once. + * + * @since 9.0.0 + * + * @return void + */ + public function setUpAllTargets() + { + $this->allTargets = $this->sniffTargets + $this->targetsInList; + } + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.0') === false); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->bowOutEarly() === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === \T_OPEN_SHORT_ARRAY + && $this->isShortList($phpcsFile, $stackPtr) === false + ) { + // Short array, not short list. + return; + } + + if ($tokens[$stackPtr]['code'] === \T_LIST) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false + || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false + ) { + // Parse error or live coding. + return; + } + + $opener = $nextNonEmpty; + $closer = $tokens[$nextNonEmpty]['parenthesis_closer']; + } else { + // Short list syntax. + $opener = $stackPtr; + + if (isset($tokens[$stackPtr]['bracket_closer'])) { + $closer = $tokens[$stackPtr]['bracket_closer']; + } + } + + if (isset($opener, $closer) === false) { + return; + } + + $this->examineList($phpcsFile, $opener, $closer); + } + + + /** + * Examine the contents of a list construct to determine whether an error needs to be thrown. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $opener The position of the list open token. + * @param int $closer The position of the list close token. + * + * @return void + */ + protected function examineList(File $phpcsFile, $opener, $closer) + { + $start = $opener; + while (($start = $this->hasTargetInList($phpcsFile, $start, $closer)) !== false) { + $phpcsFile->addError( + 'Specifying keys in list constructs is not supported in PHP 7.0 or earlier.', + $start, + 'Found' + ); + } + } + + + /** + * Check whether a certain target token exists within a list construct. + * + * Skips past nested list constructs, so these can be examined based on their own token. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $start The position of the list open token or a token + * within the list to start (resume) the examination from. + * @param int $closer The position of the list close token. + * + * @return int|bool Stack pointer to the target token if encountered. False otherwise. + */ + protected function hasTargetInList(File $phpcsFile, $start, $closer) + { + $tokens = $phpcsFile->getTokens(); + + for ($i = ($start + 1); $i < $closer; $i++) { + if (isset($this->allTargets[$tokens[$i]['code']]) === false) { + continue; + } + + if (isset($this->targetsInList[$tokens[$i]['code']]) === true) { + return $i; + } + + // Skip past nested list constructs. + if ($tokens[$i]['code'] === \T_LIST) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($nextNonEmpty !== false + && $tokens[$nextNonEmpty]['code'] === \T_OPEN_PARENTHESIS + && isset($tokens[$nextNonEmpty]['parenthesis_closer']) === true + ) { + $i = $tokens[$nextNonEmpty]['parenthesis_closer']; + } + } elseif ($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY + && isset($tokens[$i]['bracket_closer']) + ) { + $i = $tokens[$i]['bracket_closer']; + } + } + + return false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php new file mode 100644 index 000000000..ebcd7c8ef --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewListReferenceAssignmentSniff.php @@ -0,0 +1,74 @@ + \T_BITWISE_AND, + ); + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.2') === false); + } + + /** + * Examine the contents of a list construct to determine whether an error needs to be thrown. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $opener The position of the list open token. + * @param int $closer The position of the list close token. + * + * @return void + */ + protected function examineList(File $phpcsFile, $opener, $closer) + { + $start = $opener; + while (($start = $this->hasTargetInList($phpcsFile, $start, $closer)) !== false) { + $phpcsFile->addError( + 'Reference assignments within list constructs are not supported in PHP 7.2 or earlier.', + $start, + 'Found' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php new file mode 100644 index 000000000..ee100fbe2 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Lists/NewShortListSniff.php @@ -0,0 +1,84 @@ +supportsBelow('7.0') === false) { + return; + } + + if ($this->isShortList($phpcsFile, $stackPtr) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $closer = $tokens[$stackPtr]['bracket_closer']; + + $hasVariable = $phpcsFile->findNext(\T_VARIABLE, ($stackPtr + 1), $closer); + if ($hasVariable === false) { + // List syntax is only valid if there are variables in it. + return; + } + + $phpcsFile->addError( + 'The shorthand list syntax "[]" to destructure arrays is not available in PHP 7.0 or earlier.', + $stackPtr, + 'Found' + ); + + return ($closer + 1); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php new file mode 100644 index 000000000..d580bac75 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/ForbiddenToStringParametersSniff.php @@ -0,0 +1,103 @@ +supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + /* + * Not a method call. + * + * Note: This disregards method calls with the method name in a variable, like: + * $method = '__toString'; + * $obj->$method(); + * However, that would be very hard to examine reliably anyway. + */ + return; + } + + if (strtolower($tokens[$nextNonEmpty]['content']) !== '__tostring') { + // Not a call to the __toString() method. + return; + } + + $openParens = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true); + if ($openParens === false || $tokens[$openParens]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a method call. + return; + } + + $closeParens = $phpcsFile->findNext(Tokens::$emptyTokens, ($openParens + 1), null, true); + if ($closeParens === false || $tokens[$closeParens]['code'] === \T_CLOSE_PARENTHESIS) { + // Not a method call. + return; + } + + // If we're still here, then this is a call to the __toString() magic method passing parameters. + $phpcsFile->addError( + 'The __toString() magic method will no longer accept passed arguments since PHP 5.3', + $stackPtr, + 'Passed' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php new file mode 100644 index 000000000..873ef1d29 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/MethodUse/NewDirectCallsToCloneSniff.php @@ -0,0 +1,117 @@ +__clone()` is now allowed. This was the only magic method + * that had a compile-time check preventing some calls to it, which doesn't make sense. + * If we allow all other magic methods to be called, there's no reason to forbid this one." + * + * PHP version 7.0 + * + * @link https://wiki.php.net/rfc/abstract_syntax_tree#directly_calling_clone_is_allowed + * @link https://www.php.net/manual/en/language.oop5.cloning.php + * + * @since 9.1.0 + */ +class NewDirectCallsToCloneSniff extends Sniff +{ + + /** + * Tokens which indicate class internal use. + * + * @since 9.3.2 + * + * @var array + */ + protected $classInternal = array( + \T_PARENT => true, + \T_SELF => true, + \T_STATIC => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.1.0 + * + * @return array + */ + public function register() + { + return array( + \T_DOUBLE_COLON, + \T_OBJECT_OPERATOR, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + /* + * Not a method call. + * + * Note: This disregards method calls with the method name in a variable, like: + * $method = '__clone'; + * $obj->$method(); + * However, that would be very hard to examine reliably anyway. + */ + return; + } + + if (strtolower($tokens[$nextNonEmpty]['content']) !== '__clone') { + // Not a call to the __clone() method. + return; + } + + $nextNextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true); + if ($nextNextNonEmpty === false || $tokens[$nextNextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + // Not a method call. + return; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevNonEmpty === false || isset($this->classInternal[$tokens[$prevNonEmpty]['code']])) { + // Class internal call to __clone(). + return; + } + + $phpcsFile->addError( + 'Direct calls to the __clone() magic method are not allowed in PHP 5.6 or earlier.', + $nextNonEmpty, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php new file mode 100644 index 000000000..85e10bcfe --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/NewPHPOpenTagEOFSniff.php @@ -0,0 +1,147 @@ + ` interpreted as an opening PHP tag. Previously it was interpreted either as + * > ` interpreted as a literal `shortOpenTags = (bool) ini_get('short_open_tag'); + if ($this->shortOpenTags === false) { + $targets[] = \T_INLINE_HTML; + } else { + $targets[] = \T_STRING; + } + + if (version_compare(\PHP_VERSION_ID, '70399', '>')) { + $targets[] = \T_OPEN_TAG; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('7.3') === false) { + return; + } + + if ($stackPtr !== ($phpcsFile->numTokens - 1)) { + // We're only interested in the last token in the file. + return; + } + + $tokens = $phpcsFile->getTokens(); + $contents = $tokens[$stackPtr]['content']; + $error = false; + + switch ($tokens[$stackPtr]['code']) { + case \T_INLINE_HTML: + // PHP < 7.4 with short open tags off. + if ($contents === 'addError( + 'A PHP open tag at the end of a file, without trailing newline, was not supported in PHP 7.3 or earlier and would result in a syntax error or be interpreted as a literal string', + $stackPtr, + 'Found' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php new file mode 100644 index 000000000..47143a3dd --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/RemovedAlternativePHPTagsSniff.php @@ -0,0 +1,172 @@ +aspTags = (bool) ini_get('asp_tags'); + } + + return array( + \T_OPEN_TAG, + \T_OPEN_TAG_WITH_ECHO, + \T_INLINE_HTML, + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $openTag = $tokens[$stackPtr]; + $content = trim($openTag['content']); + + if ($content === '' || $content === ']+)?language=[\'"]?php[\'"]?(?:[^>]+)?>)`i', $content, $match) === 1 + ) { + $found = $match[1]; + $data = array( + 'Script', + $found, + ); + $errorCode = 'ScriptOpenTagFound'; + } + + if (isset($errorCode, $data)) { + $phpcsFile->addError( + '%s style opening tags have been removed in PHP 7.0. Found "%s"', + $stackPtr, + $errorCode, + $data + ); + return; + } + + // If we're still here, we can't be sure if what we found was really intended as ASP open tags. + if ($openTag['code'] === \T_INLINE_HTML && $this->aspTags === false) { + if (strpos($content, '<%') !== false) { + $error = 'Possible use of ASP style opening tags detected. ASP style opening tags have been removed in PHP 7.0. Found: %s'; + $snippet = $this->getSnippet($content, '<%'); + $data = array('<%' . $snippet); + + $phpcsFile->addWarning($error, $stackPtr, 'MaybeASPOpenTagFound', $data); + } + } + } + + + /** + * Get a snippet from a HTML token. + * + * @since 7.0.4 + * + * @param string $content The content of the HTML token. + * @param string $startAt Partial string to use as a starting point for the snippet. + * @param int $length The target length of the snippet to get. Defaults to 25. + * + * @return string + */ + protected function getSnippet($content, $startAt = '', $length = 25) + { + $startPos = 0; + + if ($startAt !== '') { + $startPos = strpos($content, $startAt); + if ($startPos !== false) { + $startPos += \strlen($startAt); + } + } + + $snippet = substr($content, $startPos, $length); + if ((\strlen($content) - $startPos) > $length) { + $snippet .= '...'; + } + + return $snippet; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php new file mode 100644 index 000000000..53dce4385 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Miscellaneous/ValidIntegersSniff.php @@ -0,0 +1,250 @@ +isLowPHPVersion = version_compare(\PHP_VERSION_ID, '50400', '<'); + + return array( + \T_LNUMBER, // Binary, octal integers. + \T_CONSTANT_ENCAPSED_STRING, // Hex numeric string. + ); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + if ($this->couldBeBinaryInteger($tokens, $stackPtr) === true) { + if ($this->supportsBelow('5.3')) { + $error = 'Binary integer literals were not present in PHP version 5.3 or earlier. Found: %s'; + if ($this->isLowPHPVersion === false) { + $data = array($token['content']); + } else { + $data = array($this->getBinaryInteger($phpcsFile, $tokens, $stackPtr)); + } + $phpcsFile->addError($error, $stackPtr, 'BinaryIntegerFound', $data); + } + + if ($this->isInvalidBinaryInteger($tokens, $stackPtr) === true) { + $error = 'Invalid binary integer detected. Found: %s'; + $data = array($this->getBinaryInteger($phpcsFile, $tokens, $stackPtr)); + $phpcsFile->addWarning($error, $stackPtr, 'InvalidBinaryIntegerFound', $data); + } + return; + } + + $isError = $this->supportsAbove('7.0'); + $data = array( $token['content'] ); + + if ($this->isInvalidOctalInteger($tokens, $stackPtr) === true) { + $this->addMessage( + $phpcsFile, + 'Invalid octal integer detected. Prior to PHP 7 this would lead to a truncated number. From PHP 7 onwards this causes a parse error. Found: %s', + $stackPtr, + $isError, + 'InvalidOctalIntegerFound', + $data + ); + return; + } + + if ($this->isHexidecimalNumericString($tokens, $stackPtr) === true) { + $this->addMessage( + $phpcsFile, + 'The behaviour of hexadecimal numeric strings was inconsistent prior to PHP 7 and support has been removed in PHP 7. Found: %s', + $stackPtr, + $isError, + 'HexNumericStringFound', + $data + ); + return; + } + } + + + /** + * Could the current token potentially be a binary integer ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function couldBeBinaryInteger($tokens, $stackPtr) + { + $token = $tokens[$stackPtr]; + + if ($token['code'] !== \T_LNUMBER) { + return false; + } + + if ($this->isLowPHPVersion === false) { + return (preg_match('`^0b[0-1]+$`iD', $token['content']) === 1); + } + // Pre-5.4, binary strings are tokenized as T_LNUMBER (0) + T_STRING ("b01010101"). + // At this point, we don't yet care whether it's a valid binary int, that's a separate check. + else { + return($token['content'] === '0' && $tokens[$stackPtr + 1]['code'] === \T_STRING && preg_match('`^b[0-9]+$`iD', $tokens[$stackPtr + 1]['content']) === 1); + } + } + + /** + * Is the current token an invalid binary integer ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isInvalidBinaryInteger($tokens, $stackPtr) + { + if ($this->couldBeBinaryInteger($tokens, $stackPtr) === false) { + return false; + } + + if ($this->isLowPHPVersion === false) { + // If it's an invalid binary int, the token will be split into two T_LNUMBER tokens. + return ($tokens[$stackPtr + 1]['code'] === \T_LNUMBER); + } else { + return (preg_match('`^b[0-1]+$`iD', $tokens[$stackPtr + 1]['content']) === 0); + } + } + + /** + * Retrieve the content of the tokens which together look like a binary integer. + * + * @since 7.0.3 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $tokens Token stack. + * @param int $stackPtr The position of the current token in + * the stack. + * + * @return string + */ + private function getBinaryInteger(File $phpcsFile, $tokens, $stackPtr) + { + $length = 2; // PHP < 5.4 T_LNUMBER + T_STRING. + + if ($this->isLowPHPVersion === false) { + $i = $stackPtr; + while ($tokens[$i]['code'] === \T_LNUMBER) { + $i++; + } + $length = ($i - $stackPtr); + } + + return $phpcsFile->getTokensAsString($stackPtr, $length); + } + + /** + * Is the current token an invalid octal integer ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isInvalidOctalInteger($tokens, $stackPtr) + { + $token = $tokens[$stackPtr]; + + if ($token['code'] === \T_LNUMBER && preg_match('`^0[0-7]*[8-9]+[0-9]*$`D', $token['content']) === 1) { + return true; + } + + return false; + } + + /** + * Is the current token a hexidecimal numeric string ? + * + * @since 7.0.3 + * + * @param array $tokens Token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isHexidecimalNumericString($tokens, $stackPtr) + { + $token = $tokens[$stackPtr]; + + if ($token['code'] === \T_CONSTANT_ENCAPSED_STRING && preg_match('`^0x[a-f0-9]+$`iD', $this->stripQuotes($token['content'])) === 1) { + return true; + } + + return false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php new file mode 100644 index 000000000..3dfe738cc --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php @@ -0,0 +1,199 @@ +>` operators. + * + * As of PHP 7.4, a deprecation warning will be thrown upon encountering an + * unparenthesized expression containing an `.` before a `+` or `-`. + * + * PHP version 7.4 + * PHP version 8.0 + * + * @link https://wiki.php.net/rfc/concatenation_precedence + * @link https://www.php.net/manual/en/language.operators.precedence.php + * + * @since 9.2.0 + */ +class ChangedConcatOperatorPrecedenceSniff extends Sniff +{ + + /** + * List of tokens with a lower operator precedence than concatenation in PHP >= 8.0. + * + * @since 9.2.0 + * + * @var array + */ + private $tokensWithLowerPrecedence = array( + 'T_BITWISE_AND' => true, + 'T_BITWISE_XOR' => true, + 'T_BITWISE_OR' => true, + 'T_COALESCE' => true, + 'T_INLINE_THEN' => true, + 'T_INLINE_ELSE' => true, + 'T_YIELD_FROM' => true, + 'T_YIELD' => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_PLUS, + \T_MINUS, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + if ($this->isUnaryPlusMinus($phpcsFile, $stackPtr) === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + for ($i = ($stackPtr - 1); $stackPtr >= 0; $i--) { + if ($tokens[$i]['code'] === \T_STRING_CONCAT) { + // Found one. + break; + } + + if ($tokens[$i]['code'] === \T_SEMICOLON + || $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET + || $tokens[$i]['code'] === \T_OPEN_TAG + || $tokens[$i]['code'] === \T_OPEN_TAG_WITH_ECHO + || $tokens[$i]['code'] === \T_COMMA + || $tokens[$i]['code'] === \T_COLON + || $tokens[$i]['code'] === \T_CASE + ) { + // If we reached any of the above tokens, we've reached the end of + // the statement without encountering a concatenation operator. + return; + } + + if ($tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET + && isset($tokens[$i]['bracket_closer']) + && $tokens[$i]['bracket_closer'] > $stackPtr + ) { + // No need to look any further, this is plus/minus within curly braces + // and we've reached the open curly. + return; + } + + if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) + && $tokens[$i]['parenthesis_closer'] > $stackPtr + ) { + // No need to look any further, this is plus/minus within parenthesis + // and we've reached the open parenthesis. + return; + } + + if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY + || $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET) + && isset($tokens[$i]['bracket_closer']) + && $tokens[$i]['bracket_closer'] > $stackPtr + ) { + // No need to look any further, this is plus/minus within a short array + // or array key square brackets and we've reached the opener. + return; + } + + if ($tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET) { + if (isset($tokens[$i]['scope_owner'])) { + // Different scope, we've passed the start of the statement. + return; + } + + if (isset($tokens[$i]['bracket_opener'])) { + $i = $tokens[$i]['bracket_opener']; + } + + continue; + } + + if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS + && isset($tokens[$i]['parenthesis_opener']) + ) { + // Skip over statements in parenthesis, including long arrays. + $i = $tokens[$i]['parenthesis_opener']; + continue; + } + + if (($tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET + || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY) + && isset($tokens[$i]['bracket_opener']) + ) { + // Skip over array keys and short arrays. + $i = $tokens[$i]['bracket_opener']; + continue; + } + + // Check for chain being broken by a token with a lower precedence. + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true + || isset(Tokens::$assignmentTokens[$tokens[$i]['code']]) === true + ) { + return; + } + + if (isset($this->tokensWithLowerPrecedence[$tokens[$i]['type']]) === true) { + if ($tokens[$i]['code'] === \T_BITWISE_AND + && $phpcsFile->isReference($i) === true + ) { + continue; + } + + return; + } + } + + $message = 'Using an unparenthesized expression containing a "." before a "+" or "-" has been deprecated in PHP 7.4'; + $isError = false; + if ($this->supportsAbove('8.0') === true) { + $message .= ' and removed in PHP 8.0'; + $isError = true; + } + + $this->addMessage($phpcsFile, $message, $i, $isError); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php new file mode 100644 index 000000000..740e7dfdd --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php @@ -0,0 +1,109 @@ + true, + \T_COMMA => true, + \T_DOUBLE_ARROW => true, + \T_SEMICOLON => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.0 + * @since 8.2.0 Now registers all bitshift tokens, not just bitshift right (`T_SR`). + * + * @return array + */ + public function register() + { + return array( + \T_SL, + \T_SL_EQUAL, + \T_SR, + \T_SR_EQUAL, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Determine the start and end of the part of the statement we need to examine. + $start = ($stackPtr + 1); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true); + if ($next !== false && $tokens[$next]['code'] === \T_OPEN_PARENTHESIS) { + $start = ($next + 1); + } + + $end = PHPCSHelper::findEndOfStatement($phpcsFile, $start); + if (isset($this->inclusiveStopPoints[$tokens[$end]['code']]) === true) { + --$end; + } + + if ($this->isNegativeNumber($phpcsFile, $start, $end, true) !== true) { + // Not a negative number or undetermined. + return; + } + + $phpcsFile->addError( + 'Bitwise shifts by negative number will throw an ArithmeticError in PHP 7.0. Found: %s', + $stackPtr, + 'Found', + array($phpcsFile->getTokensAsString($start, ($end - $start + 1))) + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php new file mode 100644 index 000000000..7c50ad86a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php @@ -0,0 +1,317 @@ + array(string => bool|string)) + */ + protected $newOperators = array( + 'T_POW' => array( + '5.5' => false, + '5.6' => true, + 'description' => 'power operator (**)', + ), // Identified in PHP < 5.6 icw PHPCS < 2.4.0 as T_MULTIPLY + T_MULTIPLY. + 'T_POW_EQUAL' => array( + '5.5' => false, + '5.6' => true, + 'description' => 'power assignment operator (**=)', + ), // Identified in PHP < 5.6 icw PHPCS < 2.6.0 as T_MULTIPLY + T_MUL_EQUAL. + 'T_SPACESHIP' => array( + '5.6' => false, + '7.0' => true, + 'description' => 'spaceship operator (<=>)', + ), // Identified in PHP < 7.0 icw PHPCS < 2.5.1 as T_IS_SMALLER_OR_EQUAL + T_GREATER_THAN. + 'T_COALESCE' => array( + '5.6' => false, + '7.0' => true, + 'description' => 'null coalescing operator (??)', + ), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN. + 'T_COALESCE_EQUAL' => array( + '7.3' => false, + '7.4' => true, + 'description' => 'null coalesce equal operator (??=)', + ), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN + T_EQUAL and between PHPCS 2.6.2 and PHPCS 2.8.1 as T_COALESCE + T_EQUAL. + ); + + + /** + * A list of new operators which are not recognized in older PHPCS versions. + * + * The array lists an alternative token to listen for. + * + * @since 7.0.3 + * + * @var array(string => int) + */ + protected $newOperatorsPHPCSCompat = array( + 'T_POW' => \T_MULTIPLY, + 'T_POW_EQUAL' => \T_MUL_EQUAL, + 'T_SPACESHIP' => \T_GREATER_THAN, + 'T_COALESCE' => \T_INLINE_THEN, + 'T_COALESCE_EQUAL' => \T_EQUAL, + ); + + /** + * Token translation table for older PHPCS versions. + * + * The 'before' index lists the token which would have to be directly before the + * token found for it to be one of the new operators. + * The 'real_token' index indicates which operator was found in that case. + * + * If the token combination has multi-layer complexity, such as is the case + * with T_COALESCE(_EQUAL), a 'callback' index is added instead pointing to a + * separate function which can determine whether this is the targetted token across + * PHP and PHPCS versions. + * + * {@internal 'before' was chosen rather than 'after' as that allowed for a 1-on-1 + * translation list with the current tokens.} + * + * @since 7.0.3 + * + * @var array(string => array(string => string)) + */ + protected $PHPCSCompatTranslate = array( + 'T_MULTIPLY' => array( + 'before' => 'T_MULTIPLY', + 'real_token' => 'T_POW', + ), + 'T_MUL_EQUAL' => array( + 'before' => 'T_MULTIPLY', + 'real_token' => 'T_POW_EQUAL', + ), + 'T_GREATER_THAN' => array( + 'before' => 'T_IS_SMALLER_OR_EQUAL', + 'real_token' => 'T_SPACESHIP', + ), + 'T_INLINE_THEN' => array( + 'callback' => 'isTCoalesce', + 'real_token' => 'T_COALESCE', + ), + 'T_EQUAL' => array( + 'callback' => 'isTCoalesceEqual', + 'real_token' => 'T_COALESCE_EQUAL', + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.6 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->newOperators as $token => $versions) { + if (\defined($token)) { + $tokens[] = constant($token); + } elseif (isset($this->newOperatorsPHPCSCompat[$token])) { + $tokens[] = $this->newOperatorsPHPCSCompat[$token]; + } + } + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.6 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Translate older PHPCS token combis for new operators to the actual operator. + if (isset($this->newOperators[$tokenType]) === false) { + if (isset($this->PHPCSCompatTranslate[$tokenType]) + && ((isset($this->PHPCSCompatTranslate[$tokenType]['before'], $tokens[$stackPtr - 1]) === true + && $tokens[$stackPtr - 1]['type'] === $this->PHPCSCompatTranslate[$tokenType]['before']) + || (isset($this->PHPCSCompatTranslate[$tokenType]['callback']) === true + && \call_user_func(array($this, $this->PHPCSCompatTranslate[$tokenType]['callback']), $tokens, $stackPtr) === true)) + ) { + $tokenType = $this->PHPCSCompatTranslate[$tokenType]['real_token']; + } + } elseif ($tokenType === 'T_COALESCE') { + // Make sure that T_COALESCE is not confused with T_COALESCE_EQUAL. + if (isset($tokens[($stackPtr + 1)]) !== false && $tokens[($stackPtr + 1)]['code'] === \T_EQUAL) { + // Ignore as will be dealt with via the T_EQUAL token. + return; + } + } + + // If the translation did not yield one of the tokens we are looking for, bow out. + if (isset($this->newOperators[$tokenType]) === false) { + return; + } + + $itemInfo = array( + 'name' => $tokenType, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newOperators[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 7.1.0 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 7.1.0 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 7.1.0 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + return $data; + } + + + /** + * Callback function to determine whether a T_EQUAL token is really a T_COALESCE_EQUAL token. + * + * @since 7.1.2 + * + * @param array $tokens The token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isTCoalesceEqual($tokens, $stackPtr) + { + if ($tokens[$stackPtr]['code'] !== \T_EQUAL || isset($tokens[($stackPtr - 1)]) === false) { + // Function called for wrong token or token has no predecessor. + return false; + } + + if ($tokens[($stackPtr - 1)]['type'] === 'T_COALESCE') { + return true; + } + if ($tokens[($stackPtr - 1)]['type'] === 'T_INLINE_THEN' + && (isset($tokens[($stackPtr - 2)]) && $tokens[($stackPtr - 2)]['type'] === 'T_INLINE_THEN') + ) { + return true; + } + + return false; + } + + /** + * Callback function to determine whether a T_INLINE_THEN token is really a T_COALESCE token. + * + * @since 7.1.2 + * + * @param array $tokens The token stack. + * @param int $stackPtr The current position in the token stack. + * + * @return bool + */ + private function isTCoalesce($tokens, $stackPtr) + { + if ($tokens[$stackPtr]['code'] !== \T_INLINE_THEN || isset($tokens[($stackPtr - 1)]) === false) { + // Function called for wrong token or token has no predecessor. + return false; + } + + if ($tokens[($stackPtr - 1)]['code'] === \T_INLINE_THEN) { + // Make sure not to confuse it with the T_COALESCE_EQUAL token. + if (isset($tokens[($stackPtr + 1)]) === false || $tokens[($stackPtr + 1)]['code'] !== \T_EQUAL) { + return true; + } + } + + return false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php new file mode 100644 index 000000000..b65da5974 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php @@ -0,0 +1,73 @@ +supportsBelow('5.2') === false) { + return; + } + + if ($this->isShortTernary($phpcsFile, $stackPtr) === false) { + return; + } + + $phpcsFile->addError( + 'Middle may not be omitted from ternary operators in PHP < 5.3', + $stackPtr, + 'MiddleMissing' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php new file mode 100644 index 000000000..21eca02b8 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php @@ -0,0 +1,157 @@ + true, + 'T_YIELD' => true, + 'T_LOGICAL_AND' => true, + 'T_LOGICAL_OR' => true, + 'T_LOGICAL_XOR' => true, + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.2.0 + * + * @return array + */ + public function register() + { + return array(\T_INLINE_THEN); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $endOfStatement = PHPCSHelper::findEndOfStatement($phpcsFile, $stackPtr); + if ($tokens[$endOfStatement]['code'] !== \T_SEMICOLON + && $tokens[$endOfStatement]['code'] !== \T_COLON + && $tokens[$endOfStatement]['code'] !== \T_COMMA + && $tokens[$endOfStatement]['code'] !== \T_DOUBLE_ARROW + && $tokens[$endOfStatement]['code'] !== \T_OPEN_TAG + && $tokens[$endOfStatement]['code'] !== \T_CLOSE_TAG + ) { + // End of statement is last non-empty before close brace, so make sure we examine that token too. + ++$endOfStatement; + } + + $ternaryCount = 0; + $elseCount = 0; + $shortTernaryCount = 0; + + // Start at $stackPtr so we don't need duplicate code for short ternary determination. + for ($i = $stackPtr; $i < $endOfStatement; $i++) { + if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY + || $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET + || $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET) + && isset($tokens[$i]['bracket_closer']) + ) { + // Skip over short arrays, array access keys and curlies. + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) + ) { + // Skip over anything between parentheses. + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + // Check for operators with lower operator precedence. + if (isset(Tokens::$assignmentTokens[$tokens[$i]['code']]) + || isset($this->tokensWithLowerPrecedence[$tokens[$i]['code']]) + ) { + break; + } + + if ($tokens[$i]['code'] === \T_INLINE_THEN) { + ++$ternaryCount; + + if ($this->isShortTernary($phpcsFile, $i) === true) { + ++$shortTernaryCount; + } + + continue; + } + + if ($tokens[$i]['code'] === \T_INLINE_ELSE) { + if (($ternaryCount - $elseCount) >= 2) { + // This is the `else` for a ternary in the middle part of a previous ternary. + --$ternaryCount; + } else { + ++$elseCount; + } + continue; + } + } + + if ($ternaryCount > 1 && $ternaryCount === $elseCount && $ternaryCount > $shortTernaryCount) { + $message = 'The left-associativity of the ternary operator has been deprecated in PHP 7.4'; + $isError = false; + if ($this->supportsAbove('8.0') === true) { + $message .= ' and removed in PHP 8.0'; + $isError = true; + } + + $message .= '. Multiple consecutive ternaries detected. Use parenthesis to clarify the order in which the operations should be executed'; + + $this->addMessage($phpcsFile, $message, $stackPtr, $isError); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php new file mode 100644 index 000000000..30452a095 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenGetClassNullSniff.php @@ -0,0 +1,84 @@ + true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + if ($parameters[1]['raw'] !== 'null') { + return; + } + + $phpcsFile->addError( + 'Passing "null" as the $object to get_class() is not allowed since PHP 7.2.', + $parameters[1]['start'], + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php new file mode 100644 index 000000000..9ecae5c85 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/ForbiddenStripTagsSelfClosingXHTMLSniff.php @@ -0,0 +1,113 @@ + true, + ); + + /** + * Text string tokens to examine. + * + * @since 9.3.0 + * + * @var array + */ + private $textStringTokens = array( + \T_CONSTANT_ENCAPSED_STRING => true, + \T_DOUBLE_QUOTED_STRING => true, + \T_INLINE_HTML => true, + \T_HEREDOC => true, + \T_NOWDOC => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('5.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[2]; + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] === \T_STRING + || $tokens[$i]['code'] === \T_VARIABLE + ) { + // Variable, constant, function call. Ignore as undetermined. + return; + } + + if (isset($this->textStringTokens[$tokens[$i]['code']]) === true + && strpos($tokens[$i]['content'], '/>') !== false + ) { + + $phpcsFile->addError( + 'Self-closing XHTML tags are ignored. Only non-self-closing tags should be used in the strip_tags() $allowable_tags parameter since PHP 5.3.4. Found: %s', + $i, + 'Found', + array($targetParam['raw']) + ); + + // Only throw one error per function call. + return; + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php new file mode 100644 index 000000000..8045ac8a8 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewArrayReduceInitialTypeSniff.php @@ -0,0 +1,116 @@ + true, + ); + + /** + * Tokens which, for the purposes of this sniff, indicate that there is + * a variable element to the value passed. + * + * @since 9.0.0 + * + * @var array + */ + private $variableValueTokens = array( + \T_VARIABLE, + \T_STRING, + \T_SELF, + \T_PARENT, + \T_STATIC, + \T_DOUBLE_QUOTED_STRING, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[3]) === false) { + return; + } + + $targetParam = $parameters[3]; + if ($this->isNumber($phpcsFile, $targetParam['start'], $targetParam['end'], true) !== false) { + return; + } + + if ($this->isNumericCalculation($phpcsFile, $targetParam['start'], $targetParam['end']) === true) { + return; + } + + $error = 'Passing a non-integer as the value for $initial to array_reduce() is not supported in PHP 5.2 or lower.'; + if ($phpcsFile->findNext($this->variableValueTokens, $targetParam['start'], ($targetParam['end'] + 1)) === false) { + $phpcsFile->addError( + $error . ' Found %s', + $targetParam['start'], + 'InvalidTypeFound', + array($targetParam['raw']) + ); + } else { + $phpcsFile->addWarning( + $error . ' Variable value found. Found %s', + $targetParam['start'], + 'VariableFound', + array($targetParam['raw']) + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php new file mode 100644 index 000000000..83299822e --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewFopenModesSniff.php @@ -0,0 +1,119 @@ + true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + // Version used here should be (above) the highest version from the `newModes` control, + // structure below, i.e. the last PHP version in which a new mode was introduced. + return ($this->supportsBelow('7.1') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[2]; + $errors = array(); + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING) { + continue; + } + + if (strpos($tokens[$i]['content'], 'c+') !== false && $this->supportsBelow('5.2.5')) { + $errors['cplusFound'] = array( + 'c+', + '5.2.5', + $targetParam['raw'], + ); + } elseif (strpos($tokens[$i]['content'], 'c') !== false && $this->supportsBelow('5.2.5')) { + $errors['cFound'] = array( + 'c', + '5.2.5', + $targetParam['raw'], + ); + } + + if (strpos($tokens[$i]['content'], 'e') !== false && $this->supportsBelow('7.0.15')) { + $errors['eFound'] = array( + 'e', + '7.0.15', + $targetParam['raw'], + ); + } + } + + if (empty($errors) === true) { + return; + } + + foreach ($errors as $errorCode => $errorData) { + $phpcsFile->addError( + 'Passing "%s" as the $mode to fopen() is not supported in PHP %s or lower. Found %s', + $targetParam['start'], + $errorCode, + $errorData + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php new file mode 100644 index 000000000..188955657 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHTMLEntitiesEncodingDefaultSniff.php @@ -0,0 +1,92 @@ + 3, + 'htmlentities' => 3, + 'htmlspecialchars' => 3, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * Note: This sniff should only trigger errors when both PHP 5.3 or lower, + * as well as PHP 5.4 or higher need to be supported within the application. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.3') === false || $this->supportsAbove('5.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === true) { + return; + } + + $phpcsFile->addError( + 'The default value of the $encoding parameter for %s() was changed from ISO-8859-1 to UTF-8 in PHP 5.4. For cross-version compatibility, the $encoding parameter should be explicitly set.', + $stackPtr, + 'NotSet', + array($functionName) + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php new file mode 100644 index 000000000..297f84ec2 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewHashAlgorithmsSniff.php @@ -0,0 +1,185 @@ + array(string => bool)) + */ + protected $newAlgorithms = array( + 'md2' => array( + '5.2' => false, + '5.3' => true, + ), + 'ripemd256' => array( + '5.2' => false, + '5.3' => true, + ), + 'ripemd320' => array( + '5.2' => false, + '5.3' => true, + ), + 'salsa10' => array( + '5.2' => false, + '5.3' => true, + ), + 'salsa20' => array( + '5.2' => false, + '5.3' => true, + ), + 'snefru256' => array( + '5.2' => false, + '5.3' => true, + ), + 'sha224' => array( + '5.2' => false, + '5.3' => true, + ), + 'joaat' => array( + '5.3' => false, + '5.4' => true, + ), + 'fnv132' => array( + '5.3' => false, + '5.4' => true, + ), + 'fnv164' => array( + '5.3' => false, + '5.4' => true, + ), + 'gost-crypto' => array( + '5.5' => false, + '5.6' => true, + ), + + 'sha512/224' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha512/256' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-224' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-256' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-384' => array( + '7.0' => false, + '7.1' => true, + ), + 'sha3-512' => array( + '7.0' => false, + '7.1' => true, + ), + 'crc32c' => array( + '7.3' => false, + '7.4' => true, + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.0.7 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.0.7 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $algo = $this->getHashAlgorithmParameter($phpcsFile, $stackPtr); + if (empty($algo) || \is_string($algo) === false) { + return; + } + + // Bow out if not one of the algorithms we're targetting. + if (isset($this->newAlgorithms[$algo]) === false) { + return; + } + + // Check if the algorithm used is new. + $itemInfo = array( + 'name' => $algo, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newAlgorithms[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The %s hash algorithm is not present in PHP version %s or earlier'; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php new file mode 100644 index 000000000..2c9748caf --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIDNVariantDefaultSniff.php @@ -0,0 +1,91 @@ + 3, + 'idn_to_utf8' => 3, + ); + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * Note: This sniff should only trigger errors when both PHP 7.3 or lower, + * as well as PHP 7.4 or higher need to be supported within the application. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.3') === false || $this->supportsAbove('7.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === true) { + return; + } + + $error = 'The default value of the %s() $variant parameter has changed from INTL_IDNA_VARIANT_2003 to INTL_IDNA_VARIANT_UTS46 in PHP 7.4. For optimal cross-version compatibility, the $variant parameter should be explicitly set.'; + $phpcsFile->addError( + $error, + $stackPtr, + 'NotSet', + array($functionName) + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php new file mode 100644 index 000000000..51cc894e1 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewIconvMbstringCharsetDefaultSniff.php @@ -0,0 +1,231 @@ + 3, + 'iconv_mime_decode' => 3, + 'iconv_mime_encode' => 3, // Special case. + 'iconv_strlen' => 2, + 'iconv_strpos' => 4, + 'iconv_strrpos' => 3, + 'iconv_substr' => 4, + + 'mb_check_encoding' => 2, + 'mb_chr' => 2, + 'mb_convert_case' => 3, + 'mb_convert_encoding' => 3, + 'mb_convert_kana' => 3, + 'mb_decode_numericentity' => 3, + 'mb_encode_numericentity' => 3, + 'mb_ord' => 2, + 'mb_scrub' => 2, + 'mb_strcut' => 4, + 'mb_stripos' => 4, + 'mb_stristr' => 4, + 'mb_strlen' => 2, + 'mb_strpos' => 4, + 'mb_strrchr' => 4, + 'mb_strrichr' => 4, + 'mb_strripos' => 4, + 'mb_strrpos' => 4, + 'mb_strstr' => 4, + 'mb_strtolower' => 2, + 'mb_strtoupper' => 2, + 'mb_strwidth' => 2, + 'mb_substr_count' => 3, + 'mb_substr' => 4, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * Note: This sniff should only trigger errors when both PHP 5.5 or lower, + * as well as PHP 5.6 or higher need to be supported within the application. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('5.5') === false || $this->supportsAbove('5.6') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if ($functionLC === 'iconv_mime_encode') { + // Special case the iconv_mime_encode() function. + return $this->processIconvMimeEncode($phpcsFile, $stackPtr, $functionName, $parameters); + } + + if (isset($parameters[$this->targetFunctions[$functionLC]]) === true) { + return; + } + + $paramName = '$encoding'; + if (strpos($functionLC, 'iconv_') === 0) { + $paramName = '$charset'; + } elseif ($functionLC === 'mb_convert_encoding') { + $paramName = '$from_encoding'; + } + + $error = 'The default value of the %1$s parameter for %2$s() was changed from ISO-8859-1 to UTF-8 in PHP 5.6. For cross-version compatibility, the %1$s parameter should be explicitly set.'; + $data = array( + $paramName, + $functionName, + ); + + $phpcsFile->addError($error, $stackPtr, 'NotSet', $data); + } + + /** + * Process the parameters of a matched call to the iconv_mime_encode() function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processIconvMimeEncode(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $error = 'The default value of the %s parameter index for iconv_mime_encode() was changed from ISO-8859-1 to UTF-8 in PHP 5.6. For cross-version compatibility, the %s should be explicitly set.'; + + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === false) { + $phpcsFile->addError( + $error, + $stackPtr, + 'PreferencesNotSet', + array( + '$preferences[\'input/output-charset\']', + '$preferences[\'input-charset\'] and $preferences[\'output-charset\'] indexes', + ) + ); + + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[$this->targetFunctions[$functionLC]]; + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $targetParam['start'], ($targetParam['end'] + 1), true); + if ($firstNonEmpty === false) { + // Parse error or live coding. + return; + } + + if ($tokens[$firstNonEmpty]['code'] === \T_ARRAY + || $tokens[$firstNonEmpty]['code'] === \T_OPEN_SHORT_ARRAY + ) { + $hasInputCharset = preg_match('`([\'"])input-charset\1\s*=>`', $targetParam['raw']); + $hasOutputCharset = preg_match('`([\'"])output-charset\1\s*=>`', $targetParam['raw']); + if ($hasInputCharset === 1 && $hasOutputCharset === 1) { + // Both input as well as output charset are set. + return; + } + + if ($hasInputCharset !== 1) { + $phpcsFile->addError( + $error, + $firstNonEmpty, + 'InputPreferenceNotSet', + array( + '$preferences[\'input-charset\']', + '$preferences[\'input-charset\'] index', + ) + ); + } + + if ($hasOutputCharset !== 1) { + $phpcsFile->addError( + $error, + $firstNonEmpty, + 'OutputPreferenceNotSet', + array( + '$preferences[\'output-charset\']', + '$preferences[\'output-charset\'] index', + ) + ); + } + + return; + } + + // The $preferences parameter was passed, but it was a variable/constant/output of a function call. + $phpcsFile->addWarning( + $error, + $firstNonEmpty, + 'Undetermined', + array( + '$preferences[\'input/output-charset\']', + '$preferences[\'input-charset\'] and $preferences[\'output-charset\'] indexes', + ) + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php new file mode 100644 index 000000000..f2aea60ed --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewNegativeStringOffsetSniff.php @@ -0,0 +1,129 @@ + 1-based parameter offset of the affected parameters => parameter name. + */ + protected $targetFunctions = array( + 'file_get_contents' => array( + 4 => 'offset', + ), + 'grapheme_extract' => array( + 4 => 'start', + ), + 'grapheme_stripos' => array( + 3 => 'offset', + ), + 'grapheme_strpos' => array( + 3 => 'offset', + ), + 'iconv_strpos' => array( + 3 => 'offset', + ), + 'mb_ereg_search_setpos' => array( + 1 => 'position', + ), + 'mb_strimwidth' => array( + 2 => 'start', + 3 => 'width', + ), + 'mb_stripos' => array( + 3 => 'offset', + ), + 'mb_strpos' => array( + 3 => 'offset', + ), + 'stripos' => array( + 3 => 'offset', + ), + 'strpos' => array( + 3 => 'offset', + ), + 'substr_count' => array( + 3 => 'offset', + 4 => 'length', + ), + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.0') === false); + } + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + foreach ($this->targetFunctions[$functionLC] as $pos => $name) { + if (isset($parameters[$pos]) === false) { + continue; + } + + $targetParam = $parameters[$pos]; + + if ($this->isNegativeNumber($phpcsFile, $targetParam['start'], $targetParam['end']) === false) { + continue; + } + + $phpcsFile->addError( + 'Negative string offsets were not supported for the $%s parameter in %s() in PHP 7.0 or lower. Found %s', + $targetParam['start'], + 'Found', + array( + $name, + $functionName, + $targetParam['raw'], + ) + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php new file mode 100644 index 000000000..65339e507 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPCREModifiersSniff.php @@ -0,0 +1,127 @@ + true, + 'preg_grep' => true, + 'preg_match_all' => true, + 'preg_match' => true, + 'preg_replace_callback_array' => true, + 'preg_replace_callback' => true, + 'preg_replace' => true, + 'preg_split' => true, + ); + + /** + * Array listing newly introduced regex modifiers. + * + * The key should be the modifier (case-sensitive!). + * The value should be the PHP version in which the modifier was introduced. + * + * @since 8.2.0 + * + * @var array + */ + protected $newModifiers = array( + 'J' => array( + '7.1' => false, + '7.2' => true, + ), + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + // Version used here should be the highest version from the `$newModifiers` array, + // i.e. the last PHP version in which a new modifier was introduced. + return ($this->supportsBelow('7.2') === false); + } + + + /** + * Examine the regex modifier string. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $functionName The function which contained the pattern. + * @param string $modifiers The regex modifiers found. + * + * @return void + */ + protected function examineModifiers(File $phpcsFile, $stackPtr, $functionName, $modifiers) + { + $error = 'The PCRE regex modifier "%s" is not present in PHP version %s or earlier'; + + foreach ($this->newModifiers as $modifier => $versionArray) { + if (strpos($modifiers, $modifier) === false) { + continue; + } + + $notInVersion = ''; + foreach ($versionArray as $version => $present) { + if ($notInVersion === '' && $present === false + && $this->supportsBelow($version) === true + ) { + $notInVersion = $version; + } + } + + if ($notInVersion === '') { + continue; + } + + $errorCode = $modifier . 'ModifierFound'; + $data = array( + $modifier, + $notInVersion, + ); + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php new file mode 100644 index 000000000..7e42f3e9f --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPackFormatSniff.php @@ -0,0 +1,132 @@ + true, + ); + + /** + * List of new format character codes added to pack(). + * + * @since 9.0.0 + * + * @var array Regex pattern => Version array. + */ + protected $newFormats = array( + '`([Z])`' => array( + '5.4' => false, + '5.5' => true, + ), + '`([qQJP])`' => array( + '5.6.2' => false, + '5.6.3' => true, + ), + '`([eEgG])`' => array( + '7.0.14' => false, + '7.0.15' => true, // And 7.1.1. + ), + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsBelow('7.1') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[1]; + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING + && $tokens[$i]['code'] !== \T_DOUBLE_QUOTED_STRING + ) { + continue; + } + + $content = $tokens[$i]['content']; + if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) { + $content = $this->stripVariables($content); + } + + foreach ($this->newFormats as $pattern => $versionArray) { + if (preg_match($pattern, $content, $matches) !== 1) { + continue; + } + + foreach ($versionArray as $version => $present) { + if ($present === false && $this->supportsBelow($version) === true) { + $phpcsFile->addError( + 'Passing the $format(s) "%s" to pack() is not supported in PHP %s or lower. Found %s', + $targetParam['start'], + 'NewFormatFound', + array( + $matches[1], + $version, + $targetParam['raw'], + ) + ); + continue 2; + } + } + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php new file mode 100644 index 000000000..94a1360d3 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewPasswordAlgoConstantValuesSniff.php @@ -0,0 +1,125 @@ + 2, + 'password_needs_rehash' => 2, + ); + + /** + * Tokens types which indicate that the parameter passed is not the PHP native constant. + * + * @since 9.3.0 + * + * @var array + */ + private $invalidTokenTypes = array( + \T_NULL => true, + \T_TRUE => true, + \T_FALSE => true, + \T_LNUMBER => true, + \T_DNUMBER => true, + \T_CONSTANT_ENCAPSED_STRING => true, + \T_DOUBLE_QUOTED_STRING => true, + \T_HEREDOC => true, + \T_NOWDOC => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $functionLC = strtolower($functionName); + if (isset($parameters[$this->targetFunctions[$functionLC]]) === false) { + return; + } + + $targetParam = $parameters[$this->targetFunctions[$functionLC]]; + $tokens = $phpcsFile->getTokens(); + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if (isset($this->invalidTokenTypes[$tokens[$i]['code']]) === true) { + $phpcsFile->addWarning( + 'The value of the password hash algorithm constants has changed in PHP 7.4. Pass a PHP native constant to the %s() function instead of using the value of the constant. Found: %s', + $stackPtr, + 'NotAlgoConstant', + array( + $functionName, + $targetParam['raw'], + ) + ); + + break; + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php new file mode 100644 index 000000000..4e9f15003 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewProcOpenCmdArraySniff.php @@ -0,0 +1,136 @@ + true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return false; + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[1]; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $targetParam['start'], $targetParam['end'], true); + + if ($nextNonEmpty === false) { + // Shouldn't be possible. + return; + } + + if ($tokens[$nextNonEmpty]['code'] !== \T_ARRAY + && $tokens[$nextNonEmpty]['code'] !== \T_OPEN_SHORT_ARRAY + ) { + // Not passed as an array. + return; + } + + if ($this->supportsBelow('7.3') === true) { + $phpcsFile->addError( + 'The proc_open() function did not accept $cmd to be passed in array format in PHP 7.3 and earlier.', + $nextNonEmpty, + 'Found' + ); + } + + if ($this->supportsAbove('7.4') === true) { + if (strpos($targetParam['raw'], 'escapeshellarg(') === false) { + // Efficiency: prevent needlessly walking the array. + return; + } + + $items = $this->getFunctionCallParameters($phpcsFile, $nextNonEmpty); + + if (empty($items)) { + return; + } + + foreach ($items as $item) { + for ($i = $item['start']; $i <= $item['end']; $i++) { + if ($tokens[$i]['code'] !== \T_STRING + || $tokens[$i]['content'] !== 'escapeshellarg' + ) { + continue; + } + + // @todo Potential future enhancement: check if it's a call to the PHP native function. + + $phpcsFile->addWarning( + 'When passing proc_open() the $cmd parameter as an array, PHP will take care of any necessary argument escaping. Found: %s', + $i, + 'Invalid', + array($item['raw']) + ); + + // Only throw one error per array item. + break; + } + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php new file mode 100644 index 000000000..9d9ede05a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/NewStripTagsAllowableTagsArraySniff.php @@ -0,0 +1,152 @@ + true, + ); + + /** + * Text string tokens to examine. + * + * @since 9.3.0 + * + * @var array + */ + private $textStringTokens = array( + \T_CONSTANT_ENCAPSED_STRING => true, + \T_DOUBLE_QUOTED_STRING => true, + \T_INLINE_HTML => true, + \T_HEREDOC => true, + \T_NOWDOC => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return false; + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[2]; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $targetParam['start'], $targetParam['end'], true); + + if ($nextNonEmpty === false) { + // Shouldn't be possible. + return; + } + + if ($tokens[$nextNonEmpty]['code'] !== \T_ARRAY + && $tokens[$nextNonEmpty]['code'] !== \T_OPEN_SHORT_ARRAY + ) { + // Not passed as a hard-coded array. + return; + } + + if ($this->supportsBelow('7.3') === true) { + $phpcsFile->addError( + 'The strip_tags() function did not accept $allowable_tags to be passed in array format in PHP 7.3 and earlier.', + $nextNonEmpty, + 'Found' + ); + } + + if ($this->supportsAbove('7.4') === true) { + if (strpos($targetParam['raw'], '>') === false) { + // Efficiency: prevent needlessly walking the array. + return; + } + + $items = $this->getFunctionCallParameters($phpcsFile, $nextNonEmpty); + + if (empty($items)) { + return; + } + + foreach ($items as $item) { + for ($i = $item['start']; $i <= $item['end']; $i++) { + if ($tokens[$i]['code'] === \T_STRING + || $tokens[$i]['code'] === \T_VARIABLE + ) { + // Variable, constant, function call. Ignore complete item as undetermined. + break; + } + + if (isset($this->textStringTokens[$tokens[$i]['code']]) === true + && strpos($tokens[$i]['content'], '>') !== false + ) { + + $phpcsFile->addWarning( + 'When passing strip_tags() the $allowable_tags parameter as an array, the tags should not be enclosed in <> brackets. Found: %s', + $i, + 'Invalid', + array($item['raw']) + ); + + // Only throw one error per array item. + break; + } + } + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php new file mode 100644 index 000000000..83d4b8b31 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedHashAlgorithmsSniff.php @@ -0,0 +1,117 @@ + array(string => bool)) + */ + protected $removedAlgorithms = array( + 'salsa10' => array( + '5.4' => true, + ), + 'salsa20' => array( + '5.4' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array(\T_STRING); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $algo = $this->getHashAlgorithmParameter($phpcsFile, $stackPtr); + if (empty($algo) || \is_string($algo) === false) { + return; + } + + // Bow out if not one of the algorithms we're targetting. + if (isset($this->removedAlgorithms[$algo]) === false) { + return; + } + + $itemInfo = array( + 'name' => $algo, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedAlgorithms[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The %s hash algorithm is '; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php new file mode 100644 index 000000000..d7c7c6632 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedIconvEncodingSniff.php @@ -0,0 +1,86 @@ + true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('5.6') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $phpcsFile->addWarning( + 'All previously accepted values for the $type parameter of iconv_set_encoding() have been deprecated since PHP 5.6. Found %s', + $parameters[1]['start'], + 'DeprecatedValueFound', + $parameters[1]['raw'] + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php new file mode 100644 index 000000000..1ff0f90f3 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedImplodeFlexibleParamOrderSniff.php @@ -0,0 +1,323 @@ + true, + 'join' => true, + ); + + /** + * List of PHP native constants which should be recognized as text strings. + * + * @since 9.3.0 + * + * @var array + */ + private $constantStrings = array( + 'DIRECTORY_SEPARATOR' => true, + 'PHP_EOL' => true, + ); + + /** + * List of PHP native functions which should be recognized as returning an array. + * + * Note: The array_*() functions will always be taken into account. + * + * @since 9.3.0 + * + * @var array + */ + private $arrayFunctions = array( + 'compact' => true, + 'explode' => true, + 'range' => true, + ); + + /** + * List of PHP native array functions which should *not* be recognized as returning an array. + * + * @since 9.3.0 + * + * @var array + */ + private $arrayFunctionExceptions = array( + 'array_key_exists' => true, + 'array_key_first' => true, + 'array_key_last' => true, + 'array_multisort' => true, + 'array_pop' => true, + 'array_product' => true, + 'array_push' => true, + 'array_search' => true, + 'array_shift' => true, + 'array_sum' => true, + 'array_unshift' => true, + 'array_walk_recursive' => true, + 'array_walk' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.4') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[2]) === false) { + // Only one parameter, this must be $pieces. Bow out. + return; + } + + $tokens = $phpcsFile->getTokens(); + + /* + * Examine the first parameter. + * If there is any indication that this is an array declaration, we have an error. + */ + + $targetParam = $parameters[1]; + $start = $targetParam['start']; + $end = ($targetParam['end'] + 1); + $isOnlyText = true; + + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $start, $end, true); + if ($firstNonEmpty === false) { + // Parse error. Shouldn't be possible. + return; + } + + if ($tokens[$firstNonEmpty]['code'] === \T_OPEN_PARENTHESIS) { + $start = ($firstNonEmpty + 1); + $end = $tokens[$firstNonEmpty]['parenthesis_closer']; + } + + $hasTernary = $phpcsFile->findNext(\T_INLINE_THEN, $start, $end); + if ($hasTernary !== false + && isset($tokens[$start]['nested_parenthesis'], $tokens[$hasTernary]['nested_parenthesis']) + && count($tokens[$start]['nested_parenthesis']) === count($tokens[$hasTernary]['nested_parenthesis']) + ) { + $start = ($hasTernary + 1); + } + + for ($i = $start; $i < $end; $i++) { + $tokenCode = $tokens[$i]['code']; + + if (isset(Tokens::$emptyTokens[$tokenCode])) { + continue; + } + + if ($tokenCode === \T_STRING && isset($this->constantStrings[$tokens[$i]['content']])) { + continue; + } + + if ($hasTernary !== false && $tokenCode === \T_INLINE_ELSE) { + continue; + } + + if (isset(Tokens::$stringTokens[$tokenCode]) === false) { + $isOnlyText = false; + } + + if ($tokenCode === \T_ARRAY || $tokenCode === \T_OPEN_SHORT_ARRAY || $tokenCode === \T_ARRAY_CAST) { + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + + if ($tokenCode === \T_STRING) { + /* + * Check for specific functions which return an array (i.e. $pieces). + */ + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $end, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) { + continue; + } + + $nameLc = strtolower($tokens[$i]['content']); + if (isset($this->arrayFunctions[$nameLc]) === false + && (strpos($nameLc, 'array_') !== 0 + || isset($this->arrayFunctionExceptions[$nameLc]) === true) + ) { + continue; + } + + // Now make sure it's the PHP native function being called. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $start, true); + if ($tokens[$prevNonEmpty]['code'] === \T_DOUBLE_COLON + || $tokens[$prevNonEmpty]['code'] === \T_OBJECT_OPERATOR + ) { + // Method call, not a call to the PHP native function. + continue; + } + + if ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR + && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING + ) { + // Namespaced function. + continue; + } + + // Ok, so we know that there is an array function in the first param. + // 99.9% chance that this is $pieces, not $glue. + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + } + + if ($isOnlyText === true) { + // First parameter only contained text string tokens, i.e. glue. + return; + } + + /* + * Examine the second parameter. + */ + + $targetParam = $parameters[2]; + $start = $targetParam['start']; + $end = ($targetParam['end'] + 1); + + $firstNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $start, $end, true); + if ($firstNonEmpty === false) { + // Parse error. Shouldn't be possible. + return; + } + + if ($tokens[$firstNonEmpty]['code'] === \T_OPEN_PARENTHESIS) { + $start = ($firstNonEmpty + 1); + $end = $tokens[$firstNonEmpty]['parenthesis_closer']; + } + + $hasTernary = $phpcsFile->findNext(\T_INLINE_THEN, $start, $end); + if ($hasTernary !== false + && isset($tokens[$start]['nested_parenthesis'], $tokens[$hasTernary]['nested_parenthesis']) + && count($tokens[$start]['nested_parenthesis']) === count($tokens[$hasTernary]['nested_parenthesis']) + ) { + $start = ($hasTernary + 1); + } + + for ($i = $start; $i < $end; $i++) { + $tokenCode = $tokens[$i]['code']; + + if (isset(Tokens::$emptyTokens[$tokenCode])) { + continue; + } + + if ($tokenCode === \T_ARRAY || $tokenCode === \T_OPEN_SHORT_ARRAY || $tokenCode === \T_ARRAY_CAST) { + // Found an array, $pieces is second. + return; + } + + if ($tokenCode === \T_STRING && isset($this->constantStrings[$tokens[$i]['content']])) { + // One of the special cased, PHP native string constants found. + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + + if ($tokenCode === \T_STRING || $tokenCode === \T_VARIABLE) { + // Function call, constant or variable encountered. + // No matter what this is combined with, we won't be able to reliably determine the value. + return; + } + + if ($tokenCode === \T_CONSTANT_ENCAPSED_STRING + || $tokenCode === \T_DOUBLE_QUOTED_STRING + || $tokenCode === \T_HEREDOC + || $tokenCode === \T_NOWDOC + ) { + $this->throwNotice($phpcsFile, $stackPtr, $functionName); + return; + } + } + } + + + /** + * Throw the error/warning. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * + * @return void + */ + protected function throwNotice(File $phpcsFile, $stackPtr, $functionName) + { + $message = 'Passing the $glue and $pieces parameters in reverse order to %s has been deprecated since PHP 7.4'; + $isError = false; + $errorCode = 'Deprecated'; + $data = array($functionName); + + /* + Support for the deprecated behaviour is expected to be removed in PHP 8.0. + Once this has been implemented, this section should be uncommented. + if ($this->supportsAbove('8.0') === true) { + $message .= ' and is removed since PHP 8.0'; + $isError = true; + $errorCode = 'Removed'; + } + */ + + $message .= '; $glue should be the first parameter and $pieces the second'; + + $this->addMessage($phpcsFile, $message, $stackPtr, $isError, $errorCode, $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php new file mode 100644 index 000000000..7406d9a8a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbStrrposEncodingThirdParamSniff.php @@ -0,0 +1,149 @@ + true, + ); + + /** + * Tokens which should be recognized as text. + * + * @since 9.3.0 + * + * @var array + */ + private $textStringTokens = array( + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC, + \T_NOWDOC, + ); + + /** + * Tokens which should be recognized as numbers. + * + * @since 9.3.0 + * + * @var array + */ + private $numberTokens = array( + \T_LNUMBER => \T_LNUMBER, + \T_DNUMBER => \T_DNUMBER, + \T_MINUS => \T_MINUS, + \T_PLUS => \T_PLUS, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.3.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return $this->supportsAbove('5.2') === false; + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[3]) === false) { + // Optional third parameter not set. + return; + } + + if (isset($parameters[4]) === true) { + // Encoding set as fourth parameter. + return; + } + + $targetParam = $parameters[3]; + $targets = $this->numberTokens + Tokens::$emptyTokens; + $nonNumber = $phpcsFile->findNext($targets, $targetParam['start'], ($targetParam['end'] + 1), true); + if ($nonNumber === false) { + return; + } + + if ($this->isNumericCalculation($phpcsFile, $targetParam['start'], $targetParam['end']) === true) { + return; + } + + $hasString = $phpcsFile->findNext($this->textStringTokens, $targetParam['start'], ($targetParam['end'] + 1)); + if ($hasString === false) { + // No text strings found. Undetermined. + return; + } + + $error = 'Passing the encoding to mb_strrpos() as third parameter is soft deprecated since PHP 5.2'; + if ($this->supportsAbove('7.4') === true) { + $error .= ' and hard deprecated since PHP 7.4'; + } + + $error .= '. Use an explicit 0 as the offset in the third parameter.'; + + $phpcsFile->addWarning( + $error, + $targetParam['start'], + 'Deprecated' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php new file mode 100644 index 000000000..83e4de97a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedMbstringModifiersSniff.php @@ -0,0 +1,135 @@ + 4, + 'mb_eregi_replace' => 4, + 'mb_regex_set_options' => 1, + 'mbereg_replace' => 4, // Undocumented, but valid function alias. + 'mberegi_replace' => 4, // Undocumented, but valid function alias. + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + // Version used here should be the highest version from the `$newModifiers` array, + // i.e. the last PHP version in which a new modifier was introduced. + return ($this->supportsAbove('7.1') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 7.0.5 + * @since 8.2.0 Renamed from `process()` to `processParameters()` and removed + * logic superfluous now the sniff extends the abstract. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + $tokens = $phpcsFile->getTokens(); + $functionNameLc = strtolower($functionName); + + // Check whether the options parameter in the function call is passed. + if (isset($parameters[$this->targetFunctions[$functionNameLc]]) === false) { + return; + } + + $optionsParam = $parameters[$this->targetFunctions[$functionNameLc]]; + + $stringToken = $phpcsFile->findNext(Tokens::$stringTokens, $optionsParam['start'], $optionsParam['end'] + 1); + if ($stringToken === false) { + // No string token found in the options parameter, so skip it (e.g. variable passed in). + return; + } + + $options = ''; + + /* + * Get the content of any string tokens in the options parameter and remove the quotes and variables. + */ + for ($i = $stringToken; $i <= $optionsParam['end']; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === false) { + continue; + } + + $content = $this->stripQuotes($tokens[$i]['content']); + if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) { + $content = $this->stripVariables($content); + } + $content = trim($content); + + if (empty($content) === false) { + $options .= $content; + } + } + + if (strpos($options, 'e') !== false) { + $error = 'The Mbstring regex "e" modifier is deprecated since PHP 7.1.'; + + // The alternative mb_ereg_replace_callback() function is only available since 5.4.1. + if ($this->supportsBelow('5.4.1') === false) { + $error .= ' Use mb_ereg_replace_callback() instead (PHP 5.4.1+).'; + } + + $phpcsFile->addWarning($error, $stackPtr, 'Deprecated'); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php new file mode 100644 index 000000000..832a1f625 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedNonCryptoHashSniff.php @@ -0,0 +1,121 @@ + true, + 'hash_hmac_file' => true, + 'hash_init' => true, + 'hash_pbkdf2' => true, + ); + + /** + * List of the non-cryptographic hashes. + * + * @since 9.0.0 + * + * @var array + */ + protected $disabledCryptos = array( + 'adler32' => true, + 'crc32' => true, + 'crc32b' => true, + 'fnv132' => true, + 'fnv1a32' => true, + 'fnv164' => true, + 'fnv1a64' => true, + 'joaat' => true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('7.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $targetParam = $parameters[1]; + + if (isset($this->disabledCryptos[$this->stripQuotes($targetParam['raw'])]) === false) { + return; + } + + if (strtolower($functionName) === 'hash_init' + && (isset($parameters[2]) === false + || ($parameters[2]['raw'] !== 'HASH_HMAC' + && $parameters[2]['raw'] !== (string) \HASH_HMAC)) + ) { + // For hash_init(), these hashes are only disabled with HASH_HMAC set. + return; + } + + $phpcsFile->addError( + 'Non-cryptographic hashes are no longer accepted by function %s() since PHP 7.2. Found: %s', + $targetParam['start'], + $this->stringToErrorCode($functionName), + array( + $functionName, + $targetParam['raw'], + ) + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php new file mode 100644 index 000000000..377ed79f0 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php @@ -0,0 +1,241 @@ + true, + 'preg_filter' => true, + ); + + /** + * Regex bracket delimiters. + * + * @since 7.0.5 This array was originally contained within the `process()` method. + * + * @var array + */ + protected $doublesSeparators = array( + '{' => '}', + '[' => ']', + '(' => ')', + '<' => '>', + ); + + + /** + * Process the parameters of a matched function. + * + * @since 5.6 + * @since 8.2.0 Renamed from `process()` to `processParameters()` and removed + * logic superfluous now the sniff extends the abstract. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + // Check the first parameter in the function call as that should contain the regex(es). + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $functionNameLc = strtolower($functionName); + $firstParam = $parameters[1]; + + // Differentiate between an array of patterns passed and a single pattern. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $firstParam['start'], ($firstParam['end'] + 1), true); + if ($nextNonEmpty !== false && ($tokens[$nextNonEmpty]['code'] === \T_ARRAY || $tokens[$nextNonEmpty]['code'] === \T_OPEN_SHORT_ARRAY)) { + $arrayValues = $this->getFunctionCallParameters($phpcsFile, $nextNonEmpty); + if ($functionNameLc === 'preg_replace_callback_array') { + // For preg_replace_callback_array(), the patterns will be in the array keys. + foreach ($arrayValues as $value) { + $hasKey = $phpcsFile->findNext(\T_DOUBLE_ARROW, $value['start'], ($value['end'] + 1)); + if ($hasKey === false) { + continue; + } + + $value['end'] = ($hasKey - 1); + $value['raw'] = trim($phpcsFile->getTokensAsString($value['start'], ($hasKey - $value['start']))); + $this->processRegexPattern($value, $phpcsFile, $value['end'], $functionName); + } + + } else { + // Otherwise, the patterns will be in the array values. + foreach ($arrayValues as $value) { + $hasKey = $phpcsFile->findNext(\T_DOUBLE_ARROW, $value['start'], ($value['end'] + 1)); + if ($hasKey !== false) { + $value['start'] = ($hasKey + 1); + $value['raw'] = trim($phpcsFile->getTokensAsString($value['start'], (($value['end'] + 1) - $value['start']))); + } + + $this->processRegexPattern($value, $phpcsFile, $value['end'], $functionName); + } + } + + } else { + $this->processRegexPattern($firstParam, $phpcsFile, $stackPtr, $functionName); + } + } + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 8.2.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('5.5') === false); + } + + + /** + * Analyse a potential regex pattern for use of the /e modifier. + * + * @since 7.1.2 This logic was originally contained within the `process()` method. + * + * @param array $pattern Array containing the start and end token + * pointer of the potential regex pattern and + * the raw string value of the pattern. + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $functionName The function which contained the pattern. + * + * @return void + */ + protected function processRegexPattern($pattern, File $phpcsFile, $stackPtr, $functionName) + { + $tokens = $phpcsFile->getTokens(); + + /* + * The pattern might be build up of a combination of strings, variables + * and function calls. We are only concerned with the strings. + */ + $regex = ''; + for ($i = $pattern['start']; $i <= $pattern['end']; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $content = $this->stripQuotes($tokens[$i]['content']); + if ($tokens[$i]['code'] === \T_DOUBLE_QUOTED_STRING) { + $content = $this->stripVariables($content); + } + + $regex .= trim($content); + } + } + + // Deal with multi-line regexes which were broken up in several string tokens. + if ($tokens[$pattern['start']]['line'] !== $tokens[$pattern['end']]['line']) { + $regex = $this->stripQuotes($regex); + } + + if ($regex === '') { + // No string token found in the first parameter, so skip it (e.g. if variable passed in). + return; + } + + $regexFirstChar = substr($regex, 0, 1); + + // Make sure that the character identified as the delimiter is valid. + // Otherwise, it is a false positive caused by the string concatenation. + if (preg_match('`[a-z0-9\\\\ ]`i', $regexFirstChar) === 1) { + return; + } + + if (isset($this->doublesSeparators[$regexFirstChar])) { + $regexEndPos = strrpos($regex, $this->doublesSeparators[$regexFirstChar]); + } else { + $regexEndPos = strrpos($regex, $regexFirstChar); + } + + if ($regexEndPos !== false) { + $modifiers = substr($regex, $regexEndPos + 1); + $this->examineModifiers($phpcsFile, $stackPtr, $functionName, $modifiers); + } + } + + + /** + * Examine the regex modifier string. + * + * @since 8.2.0 Split off from the `processRegexPattern()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param string $functionName The function which contained the pattern. + * @param string $modifiers The regex modifiers found. + * + * @return void + */ + protected function examineModifiers(File $phpcsFile, $stackPtr, $functionName, $modifiers) + { + if (strpos($modifiers, 'e') !== false) { + $error = '%s() - /e modifier is deprecated since PHP 5.5'; + $isError = false; + $errorCode = 'Deprecated'; + $data = array($functionName); + + if ($this->supportsAbove('7.0')) { + $error .= ' and removed since PHP 7.0'; + $isError = true; + $errorCode = 'Removed'; + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php new file mode 100644 index 000000000..6f1eced1c --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/ParameterValues/RemovedSetlocaleStringSniff.php @@ -0,0 +1,104 @@ + true, + ); + + + /** + * Do a version check to determine if this sniff needs to run at all. + * + * @since 9.0.0 + * + * @return bool + */ + protected function bowOutEarly() + { + return ($this->supportsAbove('4.2') === false); + } + + + /** + * Process the parameters of a matched function. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the stack. + * @param string $functionName The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) + { + if (isset($parameters[1]) === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $targetParam = $parameters[1]; + + for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) { + if ($tokens[$i]['code'] !== \T_CONSTANT_ENCAPSED_STRING + && $tokens[$i]['code'] !== \T_DOUBLE_QUOTED_STRING + ) { + continue; + } + + $message = 'Passing the $category as a string to setlocale() has been deprecated since PHP 4.2'; + $isError = false; + $errorCode = 'Deprecated'; + $data = array($targetParam['raw']); + + if ($this->supportsAbove('7.0') === true) { + $message .= ' and is removed since PHP 7.0'; + $isError = true; + $errorCode = 'Removed'; + } + + $message .= '; Pass one of the LC_* constants instead. Found: %s'; + + $this->addMessage($phpcsFile, $message, $i, $isError, $errorCode, $data); + break; + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php new file mode 100644 index 000000000..96b498279 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/ForbiddenCallTimePassByReferenceSniff.php @@ -0,0 +1,259 @@ + true, + 'T_IS_NOT_EQUAL' => true, + 'T_IS_IDENTICAL' => true, + 'T_IS_NOT_IDENTICAL' => true, + 'T_IS_SMALLER_OR_EQUAL' => true, + 'T_IS_GREATER_OR_EQUAL' => true, + + // Assignment tokens. + 'T_EQUAL' => true, + 'T_AND_EQUAL' => true, + 'T_OR_EQUAL' => true, + 'T_CONCAT_EQUAL' => true, + 'T_DIV_EQUAL' => true, + 'T_MINUS_EQUAL' => true, + 'T_POW_EQUAL' => true, + 'T_MOD_EQUAL' => true, + 'T_MUL_EQUAL' => true, + 'T_PLUS_EQUAL' => true, + 'T_XOR_EQUAL' => true, + 'T_DOUBLE_ARROW' => true, + 'T_SL_EQUAL' => true, + 'T_SR_EQUAL' => true, + 'T_COALESCE_EQUAL' => true, + 'T_ZSR_EQUAL' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * + * @return array + */ + public function register() + { + return array( + \T_STRING, + \T_VARIABLE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $findTokens = Tokens::$emptyTokens; + $findTokens[] = \T_BITWISE_AND; + + $prevNonEmpty = $phpcsFile->findPrevious( + $findTokens, + ($stackPtr - 1), + null, + true + ); + + if ($prevNonEmpty !== false && \in_array($tokens[$prevNonEmpty]['type'], array('T_FUNCTION', 'T_CLASS', 'T_INTERFACE', 'T_TRAIT'), true)) { + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it can't really be a *call*. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($openBracket === false || $tokens[$openBracket]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$openBracket]['parenthesis_closer']) === false + ) { + return; + } + + // Get the function call parameters. + $parameters = $this->getFunctionCallParameters($phpcsFile, $stackPtr); + if (\count($parameters) === 0) { + return; + } + + // Which nesting level is the one we are interested in ? + $nestedParenthesisCount = 1; + if (isset($tokens[$openBracket]['nested_parenthesis'])) { + $nestedParenthesisCount = \count($tokens[$openBracket]['nested_parenthesis']) + 1; + } + + foreach ($parameters as $parameter) { + if ($this->isCallTimePassByReferenceParam($phpcsFile, $parameter, $nestedParenthesisCount) === true) { + // T_BITWISE_AND represents a pass-by-reference. + $error = 'Using a call-time pass-by-reference is deprecated since PHP 5.3'; + $isError = false; + $errorCode = 'Deprecated'; + + if ($this->supportsAbove('5.4')) { + $error .= ' and prohibited since PHP 5.4'; + $isError = true; + $errorCode = 'NotAllowed'; + } + + $this->addMessage($phpcsFile, $error, $parameter['start'], $isError, $errorCode); + } + } + } + + + /** + * Determine whether a parameter is passed by reference. + * + * @since 7.0.6 Split off from the `process()` method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $parameter Information on the current parameter + * to be examined. + * @param int $nestingLevel Target nesting level. + * + * @return bool + */ + protected function isCallTimePassByReferenceParam(File $phpcsFile, $parameter, $nestingLevel) + { + $tokens = $phpcsFile->getTokens(); + + $searchStartToken = $parameter['start'] - 1; + $searchEndToken = $parameter['end'] + 1; + $nextVariable = $searchStartToken; + do { + $nextVariable = $phpcsFile->findNext(array(\T_VARIABLE, \T_OPEN_SHORT_ARRAY, \T_CLOSURE), ($nextVariable + 1), $searchEndToken); + if ($nextVariable === false) { + return false; + } + + // Ignore anything within short array definition brackets. + if ($tokens[$nextVariable]['type'] === 'T_OPEN_SHORT_ARRAY' + && (isset($tokens[$nextVariable]['bracket_opener']) + && $tokens[$nextVariable]['bracket_opener'] === $nextVariable) + && isset($tokens[$nextVariable]['bracket_closer']) + ) { + // Skip forward to the end of the short array definition. + $nextVariable = $tokens[$nextVariable]['bracket_closer']; + continue; + } + + // Skip past closures passed as function parameters. + if ($tokens[$nextVariable]['type'] === 'T_CLOSURE' + && (isset($tokens[$nextVariable]['scope_condition']) + && $tokens[$nextVariable]['scope_condition'] === $nextVariable) + && isset($tokens[$nextVariable]['scope_closer']) + ) { + // Skip forward to the end of the closure declaration. + $nextVariable = $tokens[$nextVariable]['scope_closer']; + continue; + } + + // Make sure the variable belongs directly to this function call + // and is not inside a nested function call or array. + if (isset($tokens[$nextVariable]['nested_parenthesis']) === false + || (\count($tokens[$nextVariable]['nested_parenthesis']) !== $nestingLevel) + ) { + continue; + } + + // Checking this: $value = my_function(...[*]$arg...). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($nextVariable - 1), + $searchStartToken, + true + ); + + if ($tokenBefore === false || $tokens[$tokenBefore]['code'] !== \T_BITWISE_AND) { + // Nothing before the token or no &. + continue; + } + + if ($phpcsFile->isReference($tokenBefore) === false) { + continue; + } + + // Checking this: $value = my_function(...[*]&$arg...). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokenBefore - 1), + $searchStartToken, + true + ); + + // Prevent false positive on assign by reference and compare with reference + // within function call parameters. + if (isset($this->assignOrCompare[$tokens[$tokenBefore]['type']])) { + continue; + } + + // The found T_BITWISE_AND represents a pass-by-reference. + return true; + + } while ($nextVariable < $searchEndToken); + + // This code should never be reached, but here in case of weird bugs. + return false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php new file mode 100644 index 000000000..2cc1e5513 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php @@ -0,0 +1,199 @@ +supportsBelow('5.6') === false) { + return; + } + + $dereferencing = $this->isArrayStringDereferencing($phpcsFile, $stackPtr); + if (empty($dereferencing)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $supports54 = $this->supportsBelow('5.4'); + + foreach ($dereferencing['braces'] as $openBrace => $closeBrace) { + if ($supports54 === true + && ($tokens[$openBrace]['type'] === 'T_OPEN_SQUARE_BRACKET' + || $tokens[$openBrace]['type'] === 'T_OPEN_SHORT_ARRAY') // Work around bug #1381 in PHPCS 2.8.1 and lower. + ) { + $phpcsFile->addError( + 'Direct array dereferencing of %s is not present in PHP version 5.4 or earlier', + $openBrace, + 'Found', + array($dereferencing['type']) + ); + + continue; + } + + // PHP 7.0 Array/string dereferencing using curly braces. + if ($tokens[$openBrace]['type'] === 'T_OPEN_CURLY_BRACKET') { + $phpcsFile->addError( + 'Direct array dereferencing of %s using curly braces is not present in PHP version 5.6 or earlier', + $openBrace, + 'FoundUsingCurlies', + array($dereferencing['type']) + ); + } + } + } + + + /** + * Check if this string/array is being dereferenced. + * + * @since 9.3.0 Logic split off from the process method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array Array containing the type of access and stack pointers to the + * open/close braces involved in the array/string dereferencing; + * or an empty array if no array/string dereferencing was detected. + */ + public function isArrayStringDereferencing(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['code']) { + case \T_CONSTANT_ENCAPSED_STRING: + $type = 'string literals'; + $end = $stackPtr; + break; + + case \T_ARRAY: + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) { + // Live coding. + return array(); + } else { + $type = 'arrays'; + $end = $tokens[$stackPtr]['parenthesis_closer']; + } + break; + + case \T_OPEN_SHORT_ARRAY: + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Live coding. + return array(); + } else { + $type = 'arrays'; + $end = $tokens[$stackPtr]['bracket_closer']; + } + break; + } + + if (isset($type, $end) === false) { + // Shouldn't happen, but for some reason did. + return array(); + } + + $braces = array(); + + do { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true, null, true); + if ($nextNonEmpty === false) { + break; + } + + if ($tokens[$nextNonEmpty]['type'] === 'T_OPEN_SQUARE_BRACKET' + || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_CURLY_BRACKET' // PHP 7.0+. + || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_SHORT_ARRAY' // Work around bug #1381 in PHPCS 2.8.1 and lower. + ) { + if (isset($tokens[$nextNonEmpty]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$nextNonEmpty] = $tokens[$nextNonEmpty]['bracket_closer']; + + // Continue, just in case there is nested array access, i.e. `array(1, 2, 3)[$i][$j];`. + $end = $tokens[$nextNonEmpty]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the variable. + break; + + } while (true); + + if (empty($braces)) { + return array(); + } + + return array( + 'type' => $type, + 'braces' => $braces, + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php new file mode 100644 index 000000000..f0f66b864 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php @@ -0,0 +1,142 @@ +supportsBelow('7.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + /* + * Determine the array opener & closer. + */ + $closer = $phpcsFile->numTokens; + if ($tokens[$stackPtr]['code'] === \T_ARRAY) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['parenthesis_opener']; + + if (isset($tokens[$opener]['parenthesis_closer'])) { + $closer = $tokens[$opener]['parenthesis_closer']; + } + } else { + // Short array syntax. + $opener = $stackPtr; + + if (isset($tokens[$stackPtr]['bracket_closer'])) { + $closer = $tokens[$stackPtr]['bracket_closer']; + } + } + + $nestingLevel = 0; + if (isset($tokens[($opener + 1)]['nested_parenthesis'])) { + $nestingLevel = count($tokens[($opener + 1)]['nested_parenthesis']); + } + + for ($i = $opener; $i < $closer;) { + $i = $phpcsFile->findNext(array(\T_ELLIPSIS, \T_OPEN_SHORT_ARRAY, \T_ARRAY), ($i + 1), $closer); + if ($i === false) { + return; + } + + if ($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY) { + if (isset($tokens[$i]['bracket_closer']) === false) { + // Live coding, unfinished nested array, handle this when the array opener + // of the nested array is passed. + return; + } + + // Skip over nested short arrays. These will be handled when the array opener + // of the nested array is passed. + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === \T_ARRAY) { + if (isset($tokens[$i]['parenthesis_closer']) === false) { + // Live coding, unfinished nested array, handle this when the array opener + // of the nested array is passed. + return; + } + + // Skip over nested long arrays. These will be handled when the array opener + // of the nested array is passed. + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + // Ensure this is not function call variable unpacking. + if (isset($tokens[$i]['nested_parenthesis']) + && count($tokens[$i]['nested_parenthesis']) > $nestingLevel + ) { + continue; + } + + // Ok, found one. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + $snippet = trim($phpcsFile->getTokensAsString($i, (($nextNonEmpty - $i) + 1))); + $phpcsFile->addError( + 'Array unpacking within array declarations using the spread operator is not supported in PHP 7.3 or earlier. Found: %s', + $i, + 'Found', + array($snippet) + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php new file mode 100644 index 000000000..218f0c9fa --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewClassMemberAccessSniff.php @@ -0,0 +1,192 @@ +bar()`. + * PHP 7.0: Class member access on cloning has been added, e.g. `(clone $foo)->bar()`. + * + * As of PHP 7.0, class member access on instantiation also works when using curly braces. + * While unclear, this most likely has to do with the Uniform Variable Syntax changes. + * + * PHP version 5.4 + * PHP version 7.0 + * + * @link https://www.php.net/manual/en/language.oop5.basic.php#example-177 + * @link https://www.php.net/manual/en/language.oop5.cloning.php#language.oop5.traits.properties.example + * @link https://www.php.net/manual/en/migration54.new-features.php + * @link https://wiki.php.net/rfc/instance-method-call + * @link https://wiki.php.net/rfc/uniform_variable_syntax + * + * {@internal The reason for splitting the logic of this sniff into different methods is + * to allow re-use of the logic by the PHP 7.4 `RemovedCurlyBraceArrayAccess` sniff.} + * + * @since 8.2.0 + * @since 9.3.0 Now also detects class member access on instantiation using curly braces. + */ +class NewClassMemberAccessSniff extends Sniff +{ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.2.0 + * + * @return array + */ + public function register() + { + return array( + \T_NEW, + \T_CLONE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.2.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.6') === false) { + return; + } + + $pointers = $this->isClassMemberAccess($phpcsFile, $stackPtr); + if (empty($pointers)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $supports53 = $this->supportsBelow('5.3'); + + $error = 'Class member access on object %s was not supported in PHP %s or earlier'; + $data = array('instantiation', '5.3'); + $errorCode = 'OnNewFound'; + + if ($tokens[$stackPtr]['code'] === \T_CLONE) { + $data = array('cloning', '5.6'); + $errorCode = 'OnCloneFound'; + } + + foreach ($pointers as $open => $close) { + $itemData = $data; + $itemErrorCode = $errorCode; + + if ($tokens[$stackPtr]['code'] === \T_NEW + && $tokens[$open]['code'] !== \T_OPEN_CURLY_BRACKET + ) { + if ($supports53 === true) { + $phpcsFile->addError($error, $open, $itemErrorCode, $itemData); + } + continue; + } + + if ($tokens[$stackPtr]['code'] === \T_NEW + && $tokens[$open]['code'] === \T_OPEN_CURLY_BRACKET + ) { + // Non-curlies was already handled above. + $itemData = array('instantiation using curly braces', '5.6'); + $itemErrorCode = 'OnNewFoundUsingCurlies'; + } + + $phpcsFile->addError($error, $open, $itemErrorCode, $itemData); + } + } + + + /** + * Check if the class being instantiated/cloned is being dereferenced. + * + * @since 9.3.0 Logic split off from the process method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array Array containing the stack pointers to the object operator or + * the open/close braces involved in the class member access; + * or an empty array if no class member access was detected. + */ + public function isClassMemberAccess(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === false) { + // The `new className/clone $a` has to be in parentheses, without is not supported. + return array(); + } + + $parenthesisCloser = end($tokens[$stackPtr]['nested_parenthesis']); + $parenthesisOpener = key($tokens[$stackPtr]['nested_parenthesis']); + + if (isset($tokens[$parenthesisOpener]['parenthesis_owner']) === true) { + // If there is an owner, these parentheses are for a different purpose. + return array(); + } + + $prevBeforeParenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($parenthesisOpener - 1), null, true); + if ($prevBeforeParenthesis !== false && $tokens[$prevBeforeParenthesis]['code'] === \T_STRING) { + // This is most likely a function call with the new/cloned object as a parameter. + return array(); + } + + $braces = array(); + $end = $parenthesisCloser; + + do { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true, null, true); + if ($nextNonEmpty === false) { + break; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_OBJECT_OPERATOR) { + // No need to walk any further if this is object access. + $braces[$nextNonEmpty] = true; + break; + } + + if ($tokens[$nextNonEmpty]['code'] === \T_OPEN_SQUARE_BRACKET + || $tokens[$nextNonEmpty]['code'] === \T_OPEN_CURLY_BRACKET // PHP 7.0+. + ) { + if (isset($tokens[$nextNonEmpty]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$nextNonEmpty] = $tokens[$nextNonEmpty]['bracket_closer']; + + // Continue, just in case there is nested array access, i.e. `(new Foo())[1][0];`. + $end = $tokens[$nextNonEmpty]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end. + break; + + } while (true); + + return $braces; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php new file mode 100644 index 000000000..4fd3b2fa9 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewDynamicAccessToStaticSniff.php @@ -0,0 +1,89 @@ +supportsBelow('5.2') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Disregard `static::` as well. Late static binding is reported by another sniff. + if ($tokens[$prevNonEmpty]['code'] === \T_SELF + || $tokens[$prevNonEmpty]['code'] === \T_PARENT + || $tokens[$prevNonEmpty]['code'] === \T_STATIC + ) { + return; + } + + if ($tokens[$prevNonEmpty]['code'] === \T_STRING) { + $prevPrevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true); + + if ($tokens[$prevPrevNonEmpty]['code'] !== \T_OBJECT_OPERATOR) { + return; + } + } + + $phpcsFile->addError( + 'Static class properties and methods, as well as class constants, could not be accessed using a dynamic (variable) classname in PHP 5.2 or earlier.', + $stackPtr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php new file mode 100644 index 000000000..b24590a63 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFlexibleHeredocNowdocSniff.php @@ -0,0 +1,255 @@ +') === false) { + // Start identifier of a PHP 7.3 flexible heredoc/nowdoc. + $targets[] = \T_STRING; + } + + return $targets; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + /* + * Due to a tokenizer bug which gets hit when the PHP 7.3 heredoc/nowdoc syntax + * is used, this part of the sniff cannot possibly work on PHPCS < 2.6.0. + * See upstream issue #928. + */ + if ($this->supportsBelow('7.2') === true && version_compare(PHPCSHelper::getVersion(), '2.6.0', '>=')) { + $this->detectIndentedNonStandAloneClosingMarker($phpcsFile, $stackPtr); + } + + $tokens = $phpcsFile->getTokens(); + if ($this->supportsAbove('7.3') === true && $tokens[$stackPtr]['code'] !== \T_STRING) { + $this->detectClosingMarkerInBody($phpcsFile, $stackPtr); + } + } + + + /** + * Detect indented and/or non-stand alone closing markers. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function detectIndentedNonStandAloneClosingMarker(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $indentError = 'Heredoc/nowdoc with an indented closing marker is not supported in PHP 7.2 or earlier.'; + $indentErrorCode = 'IndentedClosingMarker'; + $trailingError = 'Having code - other than a semi-colon or new line - after the closing marker of a heredoc/nowdoc is not supported in PHP 7.2 or earlier.'; + $trailingErrorCode = 'ClosingMarkerNoNewLine'; + + if (version_compare(\PHP_VERSION_ID, '70299', '>') === true) { + + /* + * Check for indented closing marker. + */ + if (ltrim($tokens[$stackPtr]['content']) !== $tokens[$stackPtr]['content']) { + $phpcsFile->addError($indentError, $stackPtr, $indentErrorCode); + } + + /* + * Check for tokens after the closing marker. + */ + $nextNonWhitespace = $phpcsFile->findNext(array(\T_WHITESPACE, \T_SEMICOLON), ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$nextNonWhitespace]['line']) { + $phpcsFile->addError($trailingError, $stackPtr, $trailingErrorCode); + } + } else { + // For PHP < 7.3, we're only interested in T_STRING tokens. + if ($tokens[$stackPtr]['code'] !== \T_STRING) { + return; + } + + if (preg_match('`^<<<([\'"]?)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\1[\r\n]+`', $tokens[$stackPtr]['content'], $matches) !== 1) { + // Not the start of a PHP 7.3 flexible heredoc/nowdoc. + return; + } + + $identifier = $matches[2]; + + for ($i = ($stackPtr + 1); $i <= $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] !== \T_ENCAPSED_AND_WHITESPACE) { + continue; + } + + $trimmed = ltrim($tokens[$i]['content']); + + if (strpos($trimmed, $identifier) !== 0) { + continue; + } + + // OK, we've found the PHP 7.3 flexible heredoc/nowdoc closing marker. + + /* + * Check for indented closing marker. + */ + if ($trimmed !== $tokens[$i]['content']) { + // Indent found before closing marker. + $phpcsFile->addError($indentError, $i, $indentErrorCode); + } + + /* + * Check for tokens after the closing marker. + */ + // Remove the identifier. + $afterMarker = substr($trimmed, \strlen($identifier)); + // Remove a potential semi-colon at the beginning of what's left of the string. + $afterMarker = ltrim($afterMarker, ';'); + // Remove new line characters at the end of the string. + $afterMarker = rtrim($afterMarker, "\r\n"); + + if ($afterMarker !== '') { + $phpcsFile->addError($trailingError, $i, $trailingErrorCode); + } + + break; + } + } + } + + + /** + * Detect heredoc/nowdoc identifiers at the start of lines in the heredoc/nowdoc body. + * + * @since 9.0.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function detectClosingMarkerInBody(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $error = 'The body of a heredoc/nowdoc can not contain the heredoc/nowdoc closing marker as text at the start of a line since PHP 7.3.'; + $errorCode = 'ClosingMarkerNoNewLine'; + + if (version_compare(\PHP_VERSION_ID, '70299', '>') === true) { + $nextNonWhitespace = $phpcsFile->findNext(\T_WHITESPACE, ($stackPtr + 1), null, true, null, true); + if ($nextNonWhitespace === false + || $tokens[$nextNonWhitespace]['code'] === \T_SEMICOLON + || (($tokens[$nextNonWhitespace]['code'] === \T_COMMA + || $tokens[$nextNonWhitespace]['code'] === \T_STRING_CONCAT) + && $tokens[$nextNonWhitespace]['line'] !== $tokens[$stackPtr]['line']) + ) { + // This is most likely a correctly identified closing marker. + return; + } + + // The real closing tag has to be before the next heredoc/nowdoc. + $nextHereNowDoc = $phpcsFile->findNext(array(\T_START_HEREDOC, \T_START_NOWDOC), ($stackPtr + 1)); + if ($nextHereNowDoc === false) { + $nextHereNowDoc = null; + } + + $identifier = trim($tokens[$stackPtr]['content']); + $realClosingMarker = $stackPtr; + + while (($realClosingMarker = $phpcsFile->findNext(\T_STRING, ($realClosingMarker + 1), $nextHereNowDoc, false, $identifier)) !== false) { + + $prevNonWhitespace = $phpcsFile->findPrevious(\T_WHITESPACE, ($realClosingMarker - 1), null, true); + if ($prevNonWhitespace === false + || $tokens[$prevNonWhitespace]['line'] === $tokens[$realClosingMarker]['line'] + ) { + // Marker text found, but not at the start of the line. + continue; + } + + // The original T_END_HEREDOC/T_END_NOWDOC was most likely incorrect as we've found + // a possible alternative closing marker. + $phpcsFile->addError($error, $stackPtr, $errorCode); + + break; + } + + } else { + if (isset($tokens[$stackPtr]['scope_closer'], $tokens[$stackPtr]['scope_opener']) === true + && $tokens[$stackPtr]['scope_closer'] === $stackPtr + ) { + $opener = $tokens[$stackPtr]['scope_opener']; + } else { + // PHPCS < 3.0.2 did not add scope_* values for Nowdocs. + $opener = $phpcsFile->findPrevious(\T_START_NOWDOC, ($stackPtr - 1)); + if ($opener === false) { + return; + } + } + + $quotedIdentifier = preg_quote($tokens[$stackPtr]['content'], '`'); + + // Throw an error for each line in the body which starts with the identifier. + for ($i = ($opener + 1); $i < $stackPtr; $i++) { + if (preg_match('`^[ \t]*' . $quotedIdentifier . '\b`', $tokens[$i]['content']) === 1) { + $phpcsFile->addError($error, $i, $errorCode); + } + } + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php new file mode 100644 index 000000000..ac5e6b72a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionArrayDereferencingSniff.php @@ -0,0 +1,187 @@ +supportsBelow('5.6') === false) { + return; + } + + $dereferencing = $this->isFunctionArrayDereferencing($phpcsFile, $stackPtr); + if (empty($dereferencing)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $supports53 = $this->supportsBelow('5.3'); + + foreach ($dereferencing as $openBrace => $closeBrace) { + if ($supports53 === true + && $tokens[$openBrace]['type'] === 'T_OPEN_SQUARE_BRACKET' + ) { + $phpcsFile->addError( + 'Function array dereferencing is not present in PHP version 5.3 or earlier', + $openBrace, + 'Found' + ); + + continue; + } + + // PHP 7.0 function array dereferencing using curly braces. + if ($tokens[$openBrace]['type'] === 'T_OPEN_CURLY_BRACKET') { + $phpcsFile->addError( + 'Function array dereferencing using curly braces is not present in PHP version 5.6 or earlier', + $openBrace, + 'FoundUsingCurlies' + ); + } + } + } + + + /** + * Check if the return of a function/method call is being dereferenced. + * + * @since 9.3.0 Logic split off from the process method. + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array Array containing stack pointers to the open/close braces + * involved in the function dereferencing; + * or an empty array if no function dereferencing was detected. + */ + public function isFunctionArrayDereferencing(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Next non-empty token should be the open parenthesis. + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + if ($openParenthesis === false || $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS) { + return array(); + } + + // Don't throw errors during live coding. + if (isset($tokens[$openParenthesis]['parenthesis_closer']) === false) { + return array(); + } + + // Is this T_STRING really a function or method call ? + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevToken !== false + && \in_array($tokens[$prevToken]['code'], array(\T_DOUBLE_COLON, \T_OBJECT_OPERATOR), true) === false + ) { + if ($tokens[$prevToken]['code'] === \T_BITWISE_AND) { + // This may be a function declared by reference. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true); + } + + $ignore = array( + \T_FUNCTION => true, + \T_CONST => true, + \T_USE => true, + \T_NEW => true, + \T_CLASS => true, + \T_INTERFACE => true, + ); + + if (isset($ignore[$tokens[$prevToken]['code']]) === true) { + // Not a call to a PHP function or method. + return array(); + } + } + + $current = $tokens[$openParenthesis]['parenthesis_closer']; + $braces = array(); + + do { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true, null, true); + if ($nextNonEmpty === false) { + break; + } + + if ($tokens[$nextNonEmpty]['type'] === 'T_OPEN_SQUARE_BRACKET' + || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_CURLY_BRACKET' // PHP 7.0+. + ) { + if (isset($tokens[$nextNonEmpty]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$nextNonEmpty] = $tokens[$nextNonEmpty]['bracket_closer']; + + // Continue, just in case there is nested array access, i.e. `echo $foo->bar()[0][2];`. + $current = $tokens[$nextNonEmpty]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the function call. + break; + + } while (true); + + return $braces; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php new file mode 100644 index 000000000..39208b355 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewFunctionCallTrailingCommaSniff.php @@ -0,0 +1,120 @@ +supportsBelow('7.2') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$nextNonEmpty]['parenthesis_closer']) === false + ) { + return; + } + + if ($tokens[$stackPtr]['code'] === \T_STRING) { + $ignore = array( + \T_FUNCTION => true, + \T_CONST => true, + \T_USE => true, + ); + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($ignore[$tokens[$prevNonEmpty]['code']]) === true) { + // Not a function call. + return; + } + } + + $closer = $tokens[$nextNonEmpty]['parenthesis_closer']; + $lastInParenthesis = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closer - 1), $nextNonEmpty, true); + + if ($tokens[$lastInParenthesis]['code'] !== \T_COMMA) { + return; + } + + $data = array(); + switch ($tokens[$stackPtr]['code']) { + case \T_ISSET: + $data[] = 'calls to isset()'; + $errorCode = 'FoundInIsset'; + break; + + case \T_UNSET: + $data[] = 'calls to unset()'; + $errorCode = 'FoundInUnset'; + break; + + default: + $data[] = 'function calls'; + $errorCode = 'FoundInFunctionCall'; + break; + } + + $phpcsFile->addError( + 'Trailing comma\'s are not allowed in %s in PHP 7.2 or earlier', + $lastInParenthesis, + $errorCode, + $data + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php new file mode 100644 index 000000000..c60ba5c35 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/NewShortArraySniff.php @@ -0,0 +1,77 @@ +supportsBelow('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + $error = '%s is not supported in PHP 5.3 or lower'; + $data = array(); + + if ($token['type'] === 'T_OPEN_SHORT_ARRAY') { + $data[] = 'Short array syntax (open)'; + } elseif ($token['type'] === 'T_CLOSE_SHORT_ARRAY') { + $data[] = 'Short array syntax (close)'; + } + + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php new file mode 100644 index 000000000..b2c29e5ff --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedCurlyBraceArrayAccessSniff.php @@ -0,0 +1,362 @@ +newArrayStringDereferencing = new NewArrayStringDereferencingSniff(); + $this->newClassMemberAccess = new NewClassMemberAccessSniff(); + $this->newFunctionArrayDereferencing = new NewFunctionArrayDereferencingSniff(); + } + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.3.0 + * + * @return array + */ + public function register() + { + $targets = array( + array( + \T_VARIABLE, + \T_STRING, // Constants. + ), + ); + + // Registers T_ARRAY, T_OPEN_SHORT_ARRAY and T_CONSTANT_ENCAPSED_STRING. + $additionalTargets = $this->newArrayStringDereferencing->register(); + $this->newArrayStringDereferencingTargets = array_flip($additionalTargets); + $targets[] = $additionalTargets; + + // Registers T_NEW and T_CLONE. + $additionalTargets = $this->newClassMemberAccess->register(); + $this->newClassMemberAccessTargets = array_flip($additionalTargets); + $targets[] = $additionalTargets; + + // Registers T_STRING. + $additionalTargets = $this->newFunctionArrayDereferencing->register(); + $this->newFunctionArrayDereferencingTargets = array_flip($additionalTargets); + $targets[] = $additionalTargets; + + return call_user_func_array('array_merge', $targets); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.4') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $braces = array(); + + // Note: Overwriting braces in each `if` is fine as only one will match anyway. + if ($tokens[$stackPtr]['code'] === \T_VARIABLE) { + $braces = $this->isVariableArrayAccess($phpcsFile, $stackPtr); + } + + if (isset($this->newArrayStringDereferencingTargets[$tokens[$stackPtr]['code']])) { + $dereferencing = $this->newArrayStringDereferencing->isArrayStringDereferencing($phpcsFile, $stackPtr); + if (isset($dereferencing['braces'])) { + $braces = $dereferencing['braces']; + } + } + + if (isset($this->newClassMemberAccessTargets[$tokens[$stackPtr]['code']])) { + $braces = $this->newClassMemberAccess->isClassMemberAccess($phpcsFile, $stackPtr); + } + + if (isset($this->newFunctionArrayDereferencingTargets[$tokens[$stackPtr]['code']])) { + $braces = $this->newFunctionArrayDereferencing->isFunctionArrayDereferencing($phpcsFile, $stackPtr); + } + + if (empty($braces) && $tokens[$stackPtr]['code'] === \T_STRING) { + $braces = $this->isConstantArrayAccess($phpcsFile, $stackPtr); + } + + if (empty($braces)) { + return; + } + + foreach ($braces as $open => $close) { + // Some of the functions will sniff for both curlies as well as square braces. + if ($tokens[$open]['code'] !== \T_OPEN_CURLY_BRACKET) { + continue; + } + + // Make sure there is something between the braces, otherwise it's still not curly brace array access. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($open + 1), $close, true); + if ($nextNonEmpty === false) { + // Nothing between the brackets. Parse error. Ignore. + continue; + } + + // OK, so we've found curly brace array access. + $snippet = $phpcsFile->getTokensAsString($stackPtr, (($close - $stackPtr) + 1)); + $fix = $phpcsFile->addFixableWarning( + 'Curly brace syntax for accessing array elements and string offsets has been deprecated in PHP 7.4. Found: %s', + $open, + 'Found', + array($snippet) + ); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($open, '['); + $phpcsFile->fixer->replaceToken($close, ']'); + $phpcsFile->fixer->endChangeset(); + } + } + } + + + /** + * Determine whether a variable is being dereferenced using curly brace syntax. + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array An array with the stack pointers to the open/close braces of + * the curly brace array access, or an empty array if no curly + * brace array access was detected. + */ + protected function isVariableArrayAccess(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $current = $stackPtr; + $braces = array(); + + do { + $current = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true); + if ($current === false) { + break; + } + + // Skip over square bracket array access. Bracket styles can be mixed. + if ($tokens[$current]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$current]['bracket_closer']) === true + && $current === $tokens[$current]['bracket_opener'] + ) { + $current = $tokens[$current]['bracket_closer']; + continue; + } + + // Handle property access. + if ($tokens[$current]['code'] === \T_OBJECT_OPERATOR) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true); + if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_STRING) { + // Live coding or parse error. + break; + } + + $current = $nextNonEmpty; + continue; + } + + if ($tokens[$current]['code'] === \T_OPEN_CURLY_BRACKET) { + if (isset($tokens[$current]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$current] = $tokens[$current]['bracket_closer']; + + // Continue, just in case there is nested access using curly braces, i.e. `$a{$i}{$j};`. + $current = $tokens[$current]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the variable. + break; + + } while (true); + + return $braces; + } + + + /** + * Determine whether a T_STRING is a constant being dereferenced using curly brace syntax. + * + * {@internal Note: the first braces for array access to a constant, for some unknown reason, + * can never be curlies, but have to be square brackets. + * Subsequent braces can be curlies.} + * + * @since 9.3.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return array An array with the stack pointers to the open/close braces of + * the curly brace array access, or an empty array if no curly + * brace array access was detected. + */ + protected function isConstantArrayAccess(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($this->isUseOfGlobalConstant($phpcsFile, $stackPtr) === false + && $tokens[$prevNonEmpty]['code'] !== \T_DOUBLE_COLON // Class constant access. + ) { + return array(); + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return array(); + } + + if ($tokens[$nextNonEmpty]['code'] !== \T_OPEN_SQUARE_BRACKET + || isset($tokens[$nextNonEmpty]['bracket_closer']) === false + ) { + // Array access for constants must start with square brackets. + return array(); + } + + $current = $tokens[$nextNonEmpty]['bracket_closer']; + $braces = array(); + + do { + $current = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), null, true); + if ($current === false) { + break; + } + + // Skip over square bracket array access. Bracket styles can be mixed. + if ($tokens[$current]['code'] === \T_OPEN_SQUARE_BRACKET + && isset($tokens[$current]['bracket_closer']) === true + && $current === $tokens[$current]['bracket_opener'] + ) { + $current = $tokens[$current]['bracket_closer']; + continue; + } + + if ($tokens[$current]['code'] === \T_OPEN_CURLY_BRACKET) { + if (isset($tokens[$current]['bracket_closer']) === false) { + // Live coding or parse error. + break; + } + + $braces[$current] = $tokens[$current]['bracket_closer']; + + // Continue, just in case there is nested access using curly braces, i.e. `$a{$i}{$j};`. + $current = $tokens[$current]['bracket_closer']; + continue; + } + + // If we're still here, we've reached the end of the variable. + break; + + } while (true); + + return $braces; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php new file mode 100644 index 000000000..ad76828c8 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Syntax/RemovedNewReferenceSniff.php @@ -0,0 +1,80 @@ +supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prevNonEmpty === false || $tokens[$prevNonEmpty]['type'] !== 'T_BITWISE_AND') { + return; + } + + $error = 'Assigning the return value of new by reference is deprecated in PHP 5.3'; + $isError = false; + $errorCode = 'Deprecated'; + + if ($this->supportsAbove('7.0') === true) { + $error .= ' and has been removed in PHP 7.0'; + $isError = true; + $errorCode = 'Removed'; + } + + $this->addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php new file mode 100644 index 000000000..aa5a39a31 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TextStrings/NewUnicodeEscapeSequenceSniff.php @@ -0,0 +1,162 @@ +getTokens(); + + // Check whether this is a single quoted or double quoted string. + if ($tokens[$stackPtr]['code'] === \T_CONSTANT_ENCAPSED_STRING) { + + // Find the start of the - potentially multi-line - text string. + $start = $stackPtr; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['code'] === \T_WHITESPACE) { + continue; + } + + if ($tokens[$i]['code'] === \T_CONSTANT_ENCAPSED_STRING) { + $start = $i; + continue; + } + + break; + } + + try { + $textString = $this->getCompleteTextString($phpcsFile, $start, false); + } catch (PHPCS_Exception $e) { + // Something went wrong determining the start of the text string. + return; + } + + $startQuote = $textString[0]; + $endQuote = substr($textString, -1); + if (($startQuote === "'" && $endQuote === "'") + || $startQuote !== $endQuote + ) { + // Single quoted string, not our concern. + return; + } + } + + $content = $this->stripQuotes($tokens[$stackPtr]['content']); + $count = preg_match_all('`(?isValidUnicodeEscapeSequence($match[1]); + } + + if ($this->supportsBelow('5.6') === true && $valid === true) { + $phpcsFile->addError( + 'Unicode codepoint escape sequences are not supported in PHP 5.6 or earlier. Found: %s', + $stackPtr, + 'Found', + array($match[0]) + ); + } + + if ($this->supportsAbove('7.0') === true && $valid === false) { + $phpcsFile->addError( + 'Strings containing a literal \u{ followed by an invalid unicode codepoint escape sequence will cause a fatal error in PHP 7.0 and above. Escape the leading backslash to prevent this. Found: %s', + $stackPtr, + 'Invalid', + array($match[0]) + ); + } + } + } + + + /** + * Verify if the codepoint in a unicode escape sequence is valid. + * + * @since 9.3.0 + * + * @param string $codepoint The codepoint as a string. + * + * @return bool + */ + protected function isValidUnicodeEscapeSequence($codepoint) + { + if (trim($codepoint) === '') { + return false; + } + + // Check if it's a valid hex codepoint. + if (preg_match('`^[0-9A-F]+$`iD', $codepoint, $match) !== 1) { + return false; + } + + if (hexdec($codepoint) > 1114111) { + // Outside of the maximum permissable range. + return false; + } + + return true; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php new file mode 100644 index 000000000..12e47318b --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/NewTypeCastsSniff.php @@ -0,0 +1,222 @@ + array(string => bool|string)) + */ + protected $newTypeCasts = array( + 'T_UNSET_CAST' => array( + '4.4' => false, + '5.0' => true, + 'description' => 'The unset cast', + ), + 'T_BINARY_CAST' => array( + '5.2.0' => false, + '5.2.1' => true, + 'description' => 'The binary cast', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.0.1 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->newTypeCasts as $token => $versions) { + if (\defined($token)) { + $tokens[] = constant($token); + } + } + + /* + * Work around tokenizer issues. + * + * - (binary) cast is incorrectly tokenized as T_STRING_CAST by PHP and PHPCS. + * - b"something" binary cast is incorrectly tokenized as T_CONSTANT_ENCAPSED_STRING by PHP and PHPCS. + * - Since PHPCS 3.4.0, PHPCS *will* tokenize these correctly. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/1574 + */ + if (version_compare(PHPCSHelper::getVersion(), '3.4.0', '<') === true) { + $tokens[] = \T_STRING_CAST; + $tokens[] = \T_CONSTANT_ENCAPSED_STRING; + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.0.1 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Detect incorrectly tokenized binary casts. + if (isset($this->newTypeCasts[$tokenType]) === false) { + $tokenContent = $tokens[$stackPtr]['content']; + switch ($tokenType) { + case 'T_STRING_CAST': + if (preg_match('`^\(\s*binary\s*\)$`i', $tokenContent) !== 1) { + return; + } + + $tokenType = 'T_BINARY_CAST'; + break; + + case 'T_CONSTANT_ENCAPSED_STRING': + if ((strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') + || (strpos($tokenContent, "b'") === 0 && substr($tokenContent, -1) === "'") + ) { + $tokenType = 'T_BINARY_CAST'; + } else { + return; + } + break; + + } + } + + // If the translation did not yield one of the tokens we are looking for, bow out. + if (isset($this->newTypeCasts[$tokenType]) === false) { + return; + } + + $itemInfo = array( + 'name' => $tokenType, + 'content' => $tokens[$stackPtr]['content'], + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.0.1 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->newTypeCasts[$itemInfo['name']]; + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 8.0.1 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description'); + } + + + /** + * Retrieve the relevant detail (version) information for use in an error message. + * + * @since 8.0.1 + * + * @param array $itemArray Version and other information about the item. + * @param array $itemInfo Base information about the item. + * + * @return array + */ + public function getErrorInfo(array $itemArray, array $itemInfo) + { + $errorInfo = parent::getErrorInfo($itemArray, $itemInfo); + $errorInfo['description'] = $itemArray['description']; + + return $errorInfo; + } + + + /** + * Filter the error message before it's passed to PHPCS. + * + * @since 8.0.1 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + return $error . '. Found: %s'; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 8.0.1 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $errorInfo['description']; + $data[] = $itemInfo['content']; + return $data; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php new file mode 100644 index 000000000..3791f0b51 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/TypeCasts/RemovedTypeCastsSniff.php @@ -0,0 +1,158 @@ + array(string => bool|string)) + */ + protected $deprecatedTypeCasts = array( + 'T_UNSET_CAST' => array( + '7.2' => false, + 'alternative' => 'unset()', + 'description' => 'unset', + ), + 'T_DOUBLE_CAST' => array( + '7.4' => false, + 'alternative' => '(float)', + 'description' => 'real', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 8.0.1 + * + * @return array + */ + public function register() + { + $tokens = array(); + foreach ($this->deprecatedTypeCasts as $token => $versions) { + $tokens[] = constant($token); + } + + return $tokens; + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 8.0.1 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenType = $tokens[$stackPtr]['type']; + + // Special case `T_DOUBLE_CAST` as the same token is used for (float) and (double) casts. + if ($tokenType === 'T_DOUBLE_CAST' && strpos($tokens[$stackPtr]['content'], 'real') === false) { + // Float/double casts, not (real) cast. + return; + } + + $itemInfo = array( + 'name' => $tokenType, + 'description' => $this->deprecatedTypeCasts[$tokenType]['description'], + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get an array of the non-PHP-version array keys used in a sub-array. + * + * @since 8.0.1 + * + * @return array + */ + protected function getNonVersionArrayKeys() + { + return array('description', 'alternative'); + } + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 8.0.1 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->deprecatedTypeCasts[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 8.0.1 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return 'The %s cast is '; + } + + + /** + * Filter the error data before it's passed to PHPCS. + * + * @since 8.0.1 + * + * @param array $data The error data array which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return array + */ + protected function filterErrorData(array $data, array $itemInfo, array $errorInfo) + { + $data[0] = $itemInfo['description']; + return $data; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php new file mode 100644 index 000000000..1e79873cc --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php @@ -0,0 +1,187 @@ +examine === false) { + return ($phpcsFile->numTokens + 1); + } + + $phpcsVersion = PHPCSHelper::getVersion(); + + // Don't do anything if the PHPCS version used is above the minimum recommended version. + if (version_compare($phpcsVersion, self::MIN_RECOMMENDED_VERSION, '>=')) { + $this->examine = false; + return ($phpcsFile->numTokens + 1); + } + + if (version_compare($phpcsVersion, self::MIN_SUPPORTED_VERSION, '<')) { + $isError = true; + $message = 'IMPORTANT: Please be advised that the minimum PHP_CodeSniffer version the PHPCompatibility standard supports is %s. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation. The recommended version of PHP_CodeSniffer for PHPCompatibility is %s or higher.'; + $errorCode = 'Unsupported_' . $this->stringToErrorCode(self::MIN_SUPPORTED_VERSION); + $replacements = array( + self::MIN_SUPPORTED_VERSION, + $phpcsVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } else { + $isError = false; + $message = 'IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP_CodeSniffer %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation to version %s or higher.'; + $errorCode = 'BelowRecommended_' . $this->stringToErrorCode(self::MIN_RECOMMENDED_VERSION); + $replacements = array( + self::MIN_RECOMMENDED_VERSION, + $phpcsVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } + + /* + * Figure out the report width to determine how long the delimiter lines should be. + * + * This is not an exact calculation as there are a number of unknowns at the time the + * notice is thrown (whether there are other notices for the file, whether those are + * warnings or errors, whether there are auto-fixable issues etc). + * + * In other words, this is just an approximation to get a reasonably stable and + * readable message layout format. + * + * {@internal + * PHPCS has had some changes as to how the messages display over the years. + * Most significantly in 2.4.0 it was attempted to solve an issue with messages + * containing new lines. Unfortunately, that solution is buggy. + * An improved version has been pulled upstream and will hopefully make it + * into PHPCS 3.3.1/3.4.0. + * + * Anyway, this means that instead of new lines, delimiter lines will be used to improved + * the readability of the (long) message. + * + * Also, as of PHPCS 2.2.0, the report width when using the `-s` option is 8 wider than + * it should be. A patch for that is included in the same upstream PR. + * + * If/when the upstream PR has been merged and the minimum supported/recommended version + * of PHPCompatibility would go beyond that, the below code should be adjusted.} + */ + $reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth'); + if (empty($reportWidth)) { + $reportWidth = 80; + } + $showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources'); + if ($showSources === true) { + $reportWidth += 6; + } + + $messageWidth = ($reportWidth - 15); // 15 is length of " # | WARNING | ". + $delimiterLine = str_repeat('-', ($messageWidth)); + $disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHPCS to your command or add to your custom ruleset. '; + $thankYou = 'Thank you for using PHPCompatibility!'; + + $message .= ' ' . $delimiterLine; + $message .= ' ' . $disableNotice; + $message .= ' ' . $delimiterLine; + $message .= ' ' . $thankYou; + + $this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements); + + $this->examine = false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php new file mode 100644 index 000000000..7a171633f --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPSniff.php @@ -0,0 +1,182 @@ +examine === false) { + return ($phpcsFile->numTokens + 1); + } + + $phpVersion = phpversion(); + + // Don't do anything if the PHPCS version used is above the minimum recommended version. + if (version_compare($phpVersion, self::MIN_RECOMMENDED_VERSION, '>=')) { + $this->examine = false; + return ($phpcsFile->numTokens + 1); + } + + if (version_compare($phpVersion, self::MIN_SUPPORTED_VERSION, '<')) { + $isError = true; + $message = 'IMPORTANT: Please be advised that the minimum PHP version the PHPCompatibility standard supports is %s. You are currently using PHP %s. Please upgrade your PHP installation. The recommended version of PHP for PHPCompatibility is %s or higher.'; + $errorCode = 'Unsupported_' . $this->stringToErrorCode(self::MIN_SUPPORTED_VERSION); + $replacements = array( + self::MIN_SUPPORTED_VERSION, + $phpVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } else { + $isError = false; + $message = 'IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP %s. Please upgrade your PHP installation to version %s or higher.'; + $errorCode = 'BelowRecommended_' . $this->stringToErrorCode(self::MIN_RECOMMENDED_VERSION); + $replacements = array( + self::MIN_RECOMMENDED_VERSION, + $phpVersion, + self::MIN_RECOMMENDED_VERSION, + $errorCode, + ); + } + + /* + * Figure out the report width to determine how long the delimiter lines should be. + * + * This is not an exact calculation as there are a number of unknowns at the time the + * notice is thrown (whether there are other notices for the file, whether those are + * warnings or errors, whether there are auto-fixable issues etc). + * + * In other words, this is just an approximation to get a reasonably stable and + * readable message layout format. + * + * {@internal + * PHPCS has had some changes as to how the messages display over the years. + * Most significantly in 2.4.0 it was attempted to solve an issue with messages + * containing new lines. Unfortunately, that solution is buggy. + * An improved version has been pulled upstream and will hopefully make it + * into PHPCS 3.3.1/3.4.0. + * + * Anyway, this means that instead of new lines, delimiter lines will be used to improved + * the readability of the (long) message. + * + * Also, as of PHPCS 2.2.0, the report width when using the `-s` option is 8 wider than + * it should be. A patch for that is included in the same upstream PR. + * + * If/when the upstream PR has been merged and the minimum supported/recommended version + * of PHPCompatibility would go beyond that, the below code should be adjusted.} + */ + $reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth'); + if (empty($reportWidth)) { + $reportWidth = 80; + } + $showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources'); + if ($showSources === true) { + $reportWidth += 6; + } + + $messageWidth = ($reportWidth - 15); // 15 is length of " # | WARNING | ". + $delimiterLine = str_repeat('-', ($messageWidth)); + $disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHP to your command or add to your custom ruleset. '; + $thankYou = 'Thank you for using PHPCompatibility!'; + + $message .= ' ' . $delimiterLine; + $message .= ' ' . $disableNotice; + $message .= ' ' . $delimiterLine; + $message .= ' ' . $thankYou; + + $this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements); + + $this->examine = false; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php new file mode 100644 index 000000000..a681a4a3b --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewGroupUseDeclarationsSniff.php @@ -0,0 +1,118 @@ +supportsBelow('7.1') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Deal with PHPCS pre-2.6.0. + if ($token['code'] === \T_USE) { + $hasCurlyBrace = $phpcsFile->findNext(\T_OPEN_CURLY_BRACKET, ($stackPtr + 1), null, false, null, true); + if ($hasCurlyBrace === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($hasCurlyBrace - 1), null, true); + if ($prevToken === false || $tokens[$prevToken]['code'] !== \T_NS_SEPARATOR) { + return; + } + + $stackPtr = $hasCurlyBrace; + } + + // Still here ? In that case, it is a group use statement. + if ($this->supportsBelow('5.6') === true) { + $phpcsFile->addError( + 'Group use declarations are not allowed in PHP 5.6 or earlier', + $stackPtr, + 'Found' + ); + } + + $closers = array(\T_CLOSE_CURLY_BRACKET); + if (\defined('T_CLOSE_USE_GROUP')) { + $closers[] = \T_CLOSE_USE_GROUP; + } + + $closeCurly = $phpcsFile->findNext($closers, ($stackPtr + 1), null, false, null, true); + if ($closeCurly === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closeCurly - 1), null, true); + if ($tokens[$prevToken]['code'] === \T_COMMA) { + $phpcsFile->addError( + 'Trailing comma\'s are not allowed in group use statements in PHP 7.1 or earlier', + $prevToken, + 'TrailingCommaFound' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php new file mode 100644 index 000000000..2d166fb5a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/UseDeclarations/NewUseConstFunctionSniff.php @@ -0,0 +1,109 @@ + string) + */ + protected $validUseNames = array( + 'const' => true, + 'function' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 7.1.4 + * + * @return array + */ + public function register() + { + return array(\T_USE); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 7.1.4 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsBelow('5.5') !== true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding. + return; + } + + if (isset($this->validUseNames[strtolower($tokens[$nextNonEmpty]['content'])]) === false) { + // Not a `use const` or `use function` statement. + return; + } + + // `use const` and `use function` have to be followed by the function/constant name. + $functionOrConstName = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextNonEmpty + 1), null, true); + if ($functionOrConstName === false + // Identifies as T_AS or T_STRING, this covers both. + || ($tokens[$functionOrConstName]['content'] === 'as' + || $tokens[$functionOrConstName]['code'] === \T_COMMA) + ) { + // Live coding or incorrect use of reserved keyword, but that is + // covered by the ForbiddenNames sniff. + return; + } + + // Still here ? In that case we have encountered a `use const` or `use function` statement. + $phpcsFile->addError( + 'Importing functions and constants through a "use" statement is not supported in PHP 5.5 or lower.', + $nextNonEmpty, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php new file mode 100644 index 000000000..c7f715d2a --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenGlobalVariableVariableSniff.php @@ -0,0 +1,125 @@ +supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1)); + if ($endOfStatement === false) { + // No semi-colon - live coding. + return; + } + + for ($ptr = ($stackPtr + 1); $ptr <= $endOfStatement; $ptr++) { + $errorThrown = false; + $nextComma = $phpcsFile->findNext(\T_COMMA, $ptr, $endOfStatement, false, null, true); + $varEnd = ($nextComma === false) ? $endOfStatement : $nextComma; + $variable = $phpcsFile->findNext(\T_VARIABLE, $ptr, $varEnd); + $varString = trim($phpcsFile->getTokensAsString($ptr, ($varEnd - $ptr))); + $data = array($varString); + + if ($variable !== false) { + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($variable - 1), $ptr, true); + + if ($prev !== false && $tokens[$prev]['type'] === 'T_DOLLAR') { + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($variable + 1), $varEnd, true); + + if ($next !== false + && \in_array($tokens[$next]['code'], array(\T_OPEN_SQUARE_BRACKET, \T_OBJECT_OPERATOR, \T_DOUBLE_COLON), true) === true + ) { + $phpcsFile->addError( + 'Global with variable variables is not allowed since PHP 7.0. Found %s', + $variable, + 'Found', + $data + ); + $errorThrown = true; + } else { + $phpcsFile->addWarning( + 'Global with anything other than bare variables is discouraged since PHP 7.0. Found %s', + $variable, + 'NonBareVariableFound', + $data + ); + $errorThrown = true; + } + } + } + + if ($errorThrown === false) { + $dollar = $phpcsFile->findNext(\T_DOLLAR, $ptr, $varEnd); + if ($dollar !== false) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($dollar + 1), $varEnd, true); + if ($tokens[$next]['code'] === \T_OPEN_CURLY_BRACKET) { + $phpcsFile->addWarning( + 'Global with anything other than bare variables is discouraged since PHP 7.0. Found %s', + $dollar, + 'NonBareVariableFound', + $data + ); + } + } + } + + // Move the stack pointer forward to the next variable for multi-variable statements. + if ($nextComma === false) { + break; + } + $ptr = $nextComma; + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php new file mode 100644 index 000000000..fc0ddc65d --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php @@ -0,0 +1,425 @@ + \T_CLASS, + 'T_INTERFACE' => \T_INTERFACE, + 'T_TRAIT' => \T_TRAIT, + ); + + /** + * Scopes to skip over when examining the contents of functions. + * + * @since 9.1.0 + * + * @var array + */ + private $skipOverScopes = array( + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + ); + + /** + * Valid uses of $this in plain functions or methods outside object context. + * + * @since 9.1.0 + * + * @var array + */ + private $validUseOutsideObject = array( + \T_ISSET => true, + \T_EMPTY => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 9.1.0 + * + * @return array + */ + public function register() + { + if (\defined('T_ANON_CLASS')) { + $this->ooScopeTokens['T_ANON_CLASS'] = \T_ANON_CLASS; + } + + $this->skipOverScopes += $this->ooScopeTokens; + + return array( + \T_FUNCTION, + \T_CLOSURE, + \T_GLOBAL, + \T_CATCH, + \T_FOREACH, + \T_UNSET, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('7.1') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['code']) { + case \T_FUNCTION: + $this->isThisUsedAsParameter($phpcsFile, $stackPtr); + $this->isThisUsedOutsideObjectContext($phpcsFile, $stackPtr); + break; + + case \T_CLOSURE: + $this->isThisUsedAsParameter($phpcsFile, $stackPtr); + break; + + case \T_GLOBAL: + /* + * $this can no longer be imported using the `global` keyword. + * This worked in PHP 7.0, though in PHP 5.x, it would throw a + * fatal "Cannot re-assign $this" error. + */ + $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1)); + if ($endOfStatement === false) { + // No semi-colon - live coding. + return; + } + + for ($i = ($stackPtr + 1); $i < $endOfStatement; $i++) { + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') { + continue; + } + + $phpcsFile->addError( + '"$this" can no longer be used with the "global" keyword since PHP 7.1.', + $i, + 'Global' + ); + } + + break; + + case \T_CATCH: + /* + * $this can no longer be used as a catch variable. + */ + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $varPtr = $phpcsFile->findNext( + \T_VARIABLE, + ($tokens[$stackPtr]['parenthesis_opener'] + 1), + $tokens[$stackPtr]['parenthesis_closer'] + ); + + if ($varPtr === false || $tokens[$varPtr]['content'] !== '$this') { + return; + } + + $phpcsFile->addError( + '"$this" can no longer be used as a catch variable since PHP 7.1.', + $varPtr, + 'Catch' + ); + + break; + + case \T_FOREACH: + /* + * $this can no longer be used as a foreach *value* variable. + * This worked in PHP 7.0, though in PHP 5.x, it would throw a + * fatal "Cannot re-assign $this" error. + */ + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + return; + } + + $stopPtr = $phpcsFile->findPrevious( + array(\T_AS, \T_DOUBLE_ARROW), + ($tokens[$stackPtr]['parenthesis_closer'] - 1), + $tokens[$stackPtr]['parenthesis_opener'] + ); + if ($stopPtr === false) { + return; + } + + $valueVarPtr = $phpcsFile->findNext( + \T_VARIABLE, + ($stopPtr + 1), + $tokens[$stackPtr]['parenthesis_closer'] + ); + if ($valueVarPtr === false || $tokens[$valueVarPtr]['content'] !== '$this') { + return; + } + + $afterThis = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($valueVarPtr + 1), + $tokens[$stackPtr]['parenthesis_closer'], + true + ); + + if ($afterThis !== false + && ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR + || $tokens[$afterThis]['code'] === \T_DOUBLE_COLON) + ) { + return; + } + + $phpcsFile->addError( + '"$this" can no longer be used as value variable in a foreach control structure since PHP 7.1.', + $valueVarPtr, + 'ForeachValueVar' + ); + + break; + + case \T_UNSET: + /* + * $this can no longer be unset. + */ + $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($openParenthesis === false + || $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS + || isset($tokens[$openParenthesis]['parenthesis_closer']) === false + ) { + return; + } + + for ($i = ($openParenthesis + 1); $i < $tokens[$openParenthesis]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') { + continue; + } + + $afterThis = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($i + 1), + $tokens[$openParenthesis]['parenthesis_closer'], + true + ); + + if ($afterThis !== false + && ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR + || $tokens[$afterThis]['code'] === \T_DOUBLE_COLON + || $tokens[$afterThis]['code'] === \T_OPEN_SQUARE_BRACKET) + ) { + $i = $afterThis; + continue; + } + + $phpcsFile->addError( + '"$this" can no longer be unset since PHP 7.1.', + $i, + 'Unset' + ); + } + + break; + } + } + + /** + * Check if $this is used as a parameter in a function declaration. + * + * $this can no longer be used as a parameter in a *global* function. + * Use as a parameter in a method was already an error prior to PHP 7.1. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + protected function isThisUsedAsParameter(File $phpcsFile, $stackPtr) + { + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) { + return; + } + + $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr); + if (empty($params)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + foreach ($params as $param) { + if ($param['name'] !== '$this') { + continue; + } + + if ($tokens[$stackPtr]['code'] === \T_FUNCTION) { + $phpcsFile->addError( + '"$this" can no longer be used as a parameter since PHP 7.1.', + $param['token'], + 'FunctionParam' + ); + } else { + $phpcsFile->addError( + '"$this" can no longer be used as a closure parameter since PHP 7.0.7.', + $param['token'], + 'ClosureParam' + ); + } + } + } + + /** + * Check if $this is used in a plain function or method. + * + * Prior to PHP 7.1, this would result in an "undefined variable" notice + * and execution would continue with $this regarded as `null`. + * As of PHP 7.1, this throws an exception. + * + * Note: use within isset() and empty() to check object context is still allowed. + * Note: $this can still be used within a closure. + * + * @since 9.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + protected function isThisUsedOutsideObjectContext(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) { + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProps['is_static'] === false) { + return; + } else { + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === '__call') { + /* + * This is an exception. + * @link https://wiki.php.net/rfc/this_var#always_show_true_this_value_in_magic_method_call + */ + return; + } + } + } + + for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) { + if (isset($this->skipOverScopes[$tokens[$i]['type']])) { + if (isset($tokens[$i]['scope_closer']) === false) { + // Live coding or parse error, will only lead to inaccurate results. + return; + } + + // Skip over nested structures. + $i = $tokens[$i]['scope_closer']; + continue; + } + + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') { + continue; + } + + if (isset($tokens[$i]['nested_parenthesis']) === true) { + $nestedParenthesis = $tokens[$i]['nested_parenthesis']; + $nestedOpenParenthesis = array_keys($nestedParenthesis); + $lastOpenParenthesis = array_pop($nestedOpenParenthesis); + + $previousNonEmpty = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($lastOpenParenthesis - 1), + null, + true, + null, + true + ); + + if (isset($this->validUseOutsideObject[$tokens[$previousNonEmpty]['code']])) { + continue; + } + } + + $phpcsFile->addError( + '"$this" can no longer be used in a plain function or method since PHP 7.1.', + $i, + 'OutsideObjectContext' + ); + } + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php new file mode 100644 index 000000000..f7948079b --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/NewUniformVariableSyntaxSniff.php @@ -0,0 +1,114 @@ +supportsAbove('7.0') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // Verify that the next token is a square open bracket. If not, bow out. + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true); + + if ($nextToken === false || $tokens[$nextToken]['code'] !== \T_OPEN_SQUARE_BRACKET || isset($tokens[$nextToken]['bracket_closer']) === false) { + return; + } + + // The previous non-empty token has to be a $, -> or ::. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($prevToken === false || \in_array($tokens[$prevToken]['code'], array(\T_DOLLAR, \T_OBJECT_OPERATOR, \T_DOUBLE_COLON), true) === false) { + return; + } + + // For static object calls, it only applies when this is a function call. + if ($tokens[$prevToken]['code'] === \T_DOUBLE_COLON) { + $hasBrackets = $tokens[$nextToken]['bracket_closer']; + while (($hasBrackets = $phpcsFile->findNext(Tokens::$emptyTokens, ($hasBrackets + 1), null, true, null, true)) !== false) { + if ($tokens[$hasBrackets]['code'] === \T_OPEN_SQUARE_BRACKET) { + if (isset($tokens[$hasBrackets]['bracket_closer'])) { + $hasBrackets = $tokens[$hasBrackets]['bracket_closer']; + continue; + } else { + // Live coding. + return; + } + + } elseif ($tokens[$hasBrackets]['code'] === \T_OPEN_PARENTHESIS) { + // Caught! + break; + + } else { + // Not a function call, so bow out. + return; + } + } + + // Now let's also prevent false positives when used with self and static which still work fine. + $classToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true, null, true); + if ($classToken !== false) { + if ($tokens[$classToken]['code'] === \T_STATIC || $tokens[$classToken]['code'] === \T_SELF) { + return; + } elseif ($tokens[$classToken]['code'] === \T_STRING && $tokens[$classToken]['content'] === 'self') { + return; + } + } + } + + $phpcsFile->addError( + 'Indirect access to variables, properties and methods will be evaluated strictly in left-to-right order since PHP 7.0. Use curly braces to remove ambiguity.', + $stackPtr, + 'Found' + ); + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php new file mode 100644 index 000000000..c814e7dc2 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/Sniffs/Variables/RemovedPredefinedGlobalVariablesSniff.php @@ -0,0 +1,318 @@ + array(string => bool|string)) + */ + protected $removedGlobalVariables = array( + 'HTTP_POST_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_POST', + ), + 'HTTP_GET_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_GET', + ), + 'HTTP_ENV_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_ENV', + ), + 'HTTP_SERVER_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SERVER', + ), + 'HTTP_COOKIE_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_COOKIE', + ), + 'HTTP_SESSION_VARS' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_SESSION', + ), + 'HTTP_POST_FILES' => array( + '5.3' => false, + '5.4' => true, + 'alternative' => '$_FILES', + ), + + 'HTTP_RAW_POST_DATA' => array( + '5.6' => false, + '7.0' => true, + 'alternative' => 'php://input', + ), + + 'php_errormsg' => array( + '7.2' => false, + 'alternative' => 'error_get_last()', + ), + ); + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 5.5 + * @since 7.0 + * + * @return array + */ + public function register() + { + return array(\T_VARIABLE); + } + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 5.5 + * @since 7.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->supportsAbove('5.3') === false) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $varName = substr($tokens[$stackPtr]['content'], 1); + + if (isset($this->removedGlobalVariables[$varName]) === false) { + return; + } + + if ($this->isClassProperty($phpcsFile, $stackPtr) === true) { + // Ok, so this was a class property declaration, not our concern. + return; + } + + // Check for static usage of class properties shadowing the removed global variables. + if ($this->inClassScope($phpcsFile, $stackPtr, false) === true) { + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true, null, true); + if ($prevToken !== false && $tokens[$prevToken]['code'] === \T_DOUBLE_COLON) { + return; + } + } + + // Do some additional checks for the $php_errormsg variable. + if ($varName === 'php_errormsg' + && $this->isTargetPHPErrormsgVar($phpcsFile, $stackPtr, $tokens) === false + ) { + return; + } + + // Still here, so throw an error/warning. + $itemInfo = array( + 'name' => $varName, + ); + $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); + } + + + /** + * Get the relevant sub-array for a specific item from a multi-dimensional array. + * + * @since 7.1.0 + * + * @param array $itemInfo Base information about the item. + * + * @return array Version and other information about the item. + */ + public function getItemArray(array $itemInfo) + { + return $this->removedGlobalVariables[$itemInfo['name']]; + } + + + /** + * Get the error message template for this sniff. + * + * @since 7.1.0 + * + * @return string + */ + protected function getErrorMsgTemplate() + { + return "Global variable '\$%s' is "; + } + + + /** + * Filter the error message before it's passed to PHPCS. + * + * @since 8.1.0 + * + * @param string $error The error message which was created. + * @param array $itemInfo Base information about the item this error message applies to. + * @param array $errorInfo Detail information about an item this error message applies to. + * + * @return string + */ + protected function filterErrorMsg($error, array $itemInfo, array $errorInfo) + { + if ($itemInfo['name'] === 'php_errormsg') { + $error = str_replace('Global', 'The', $error); + } + return $error; + } + + /** + * Run some additional checks for the `$php_errormsg` variable. + * + * @since 8.1.0 + * + * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param array $tokens Token array of the current file. + * + * @return bool + */ + private function isTargetPHPErrormsgVar(File $phpcsFile, $stackPtr, array $tokens) + { + $scopeStart = 0; + + /* + * If the variable is detected within the scope of a function/closure, limit the checking. + */ + $function = $phpcsFile->getCondition($stackPtr, \T_CLOSURE); + if ($function === false) { + $function = $phpcsFile->getCondition($stackPtr, \T_FUNCTION); + } + + // It could also be a function param, which is not in the function scope. + if ($function === false && isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParentheses = $tokens[$stackPtr]['nested_parenthesis']; + $parenthesisCloser = end($nestedParentheses); + if (isset($tokens[$parenthesisCloser]['parenthesis_owner']) + && ($tokens[$tokens[$parenthesisCloser]['parenthesis_owner']]['code'] === \T_FUNCTION + || $tokens[$tokens[$parenthesisCloser]['parenthesis_owner']]['code'] === \T_CLOSURE) + ) { + $function = $tokens[$parenthesisCloser]['parenthesis_owner']; + } + } + + if ($function !== false) { + $scopeStart = $tokens[$function]['scope_opener']; + } + + /* + * Now, let's do some additional checks. + */ + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + // Is the variable being used as an array ? + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === \T_OPEN_SQUARE_BRACKET) { + // The PHP native variable is a string, so this is probably not it + // (except for array access to string, but why would you in this case ?). + return false; + } + + // Is this a variable assignment ? + if ($nextNonEmpty !== false + && isset(Tokens::$assignmentTokens[$tokens[$nextNonEmpty]['code']]) === true + ) { + return false; + } + + // Is this a function param shadowing the PHP native one ? + if ($function !== false) { + $parameters = PHPCSHelper::getMethodParameters($phpcsFile, $function); + if (\is_array($parameters) === true && empty($parameters) === false) { + foreach ($parameters as $param) { + if ($param['name'] === '$php_errormsg') { + return false; + } + } + } + } + + $skipPast = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + 'T_TRAIT' => true, + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + ); + + // Walk back and see if there is an assignment to the variable within the same scope. + for ($i = ($stackPtr - 1); $i >= $scopeStart; $i--) { + if ($tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET + && isset($tokens[$i]['scope_condition']) + && isset($skipPast[$tokens[$tokens[$i]['scope_condition']]['type']]) + ) { + // Skip past functions, classes etc. + $i = $tokens[$i]['scope_condition']; + continue; + } + + if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$php_errormsg') { + continue; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + + if ($nextNonEmpty !== false + && isset(Tokens::$assignmentTokens[$tokens[$nextNonEmpty]['code']]) === true + ) { + return false; + } + } + + return true; + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml new file mode 100644 index 000000000..3eb0b6734 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/PHPCompatibility/ruleset.xml @@ -0,0 +1,7 @@ + + + Coding Standard that checks for PHP version compatibility. + + ./../PHPCSAliases.php + + diff --git a/kirki-composer/phpcompatibility/php-compatibility/README.md b/kirki-composer/phpcompatibility/php-compatibility/README.md new file mode 100644 index 000000000..9b1fd51b7 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/README.md @@ -0,0 +1,250 @@ +PHP Compatibility Coding Standard for PHP CodeSniffer +===================================================== +[![Latest Stable Version](https://poser.pugx.org/phpcompatibility/php-compatibility/v/stable.png)](https://packagist.org/packages/phpcompatibility/php-compatibility) +[![Latest Unstable Version](https://poser.pugx.org/phpcompatibility/php-compatibility/v/unstable.png)](https://packagist.org/packages/phpcompatibility/php-compatibility) +![Awesome](https://img.shields.io/badge/awesome%3F-yes!-brightgreen.svg) +[![License](https://poser.pugx.org/phpcompatibility/php-compatibility/license.png)](https://github.com/PHPCompatibility/PHPCompatibility/blob/master/LICENSE) +[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=wimg&url=https://github.com/PHPCompatibility/PHPCompatibility&title=PHPCompatibility&language=&tags=github&category=software) + +[![Build Status](https://travis-ci.org/PHPCompatibility/PHPCompatibility.svg?branch=develop)](https://travis-ci.org/PHPCompatibility/PHPCompatibility) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/PHPCompatibility/PHPCompatibility/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/PHPCompatibility/PHPCompatibility/) +[![Coverage Status](https://coveralls.io/repos/github/PHPCompatibility/PHPCompatibility/badge.svg?branch=develop)](https://coveralls.io/github/PHPCompatibility/PHPCompatibility?branch=develop) + +[![Minimum PHP Version](https://img.shields.io/packagist/php-v/phpcompatibility/php-compatibility.svg?maxAge=3600)](https://packagist.org/packages/phpcompatibility/php-compatibility) +[![Tested on PHP 5.3 to nightly](https://img.shields.io/badge/tested%20on-PHP%205.3%20|%205.4%20|%205.5%20|%205.6%20|%207.0%20|%207.1%20|%207.2%20|%207.3%20|%207.4%20-brightgreen.svg?maxAge=2419200)](https://travis-ci.org/PHPCompatibility/PHPCompatibility) + + +This is a set of sniffs for [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) that checks for PHP cross-version compatibility. +It will allow you to analyse your code for compatibility with higher and lower versions of PHP. + +* [PHP Version Support](#php-version-support) +* [Requirements](#requirements) +* [Thank you](#thank-you) +* [Upgrading to PHPCompatibility 9.0.0](#warning-upgrading-to-phpcompatibility-900-warning) +* [Installation in a Composer project (method 1)](#installation-in-a-composer-project-method-1) +* [Installation via a git check-out to an arbitrary directory (method 2)](#installation-via-a-git-check-out-to-an-arbitrary-directory-method-2) +* [Sniffing your code for compatibility with specific PHP version(s)](#sniffing-your-code-for-compatibility-with-specific-php-versions) + + [Using a framework/CMS/polyfill specific ruleset](#using-a-frameworkcmspolyfill-specific-ruleset) +* [Using a custom ruleset](#using-a-custom-ruleset) + + [`testVersion` in the ruleset versus command-line](#testversion-in-the-ruleset-versus-command-line) + + [PHPCompatibility specific options](#phpcompatibility-specific-options) +* [Projects extending PHPCompatibility](#projects-extending-phpcompatibility) +* [Contributing](#contributing) +* [License](#license) + +PHP Version Support +------- + +The project aims to cover all PHP compatibility changes introduced since PHP 5.0 up to the latest PHP release. This is an ongoing process and coverage is not yet 100% (if, indeed, it ever could be). Progress is tracked on [our GitHub issue tracker](https://github.com/PHPCompatibility/PHPCompatibility/issues). + +Pull requests that check for compatibility issues in PHP 4 code - in particular between PHP 4 and PHP 5.0 - are very welcome as there are still situations where people need help upgrading legacy systems. However, coverage for changes introduced before PHP 5.1 will remain patchy as sniffs for this are not actively being developed at this time. + +Requirements +------- + +* PHP 5.3+ for use with PHP CodeSniffer 2.x. +* PHP 5.4+ for use with PHP CodeSniffer 3.x. + +PHP CodeSniffer: 2.3.0+ or 3.0.2+. + +The sniffs are designed to give the same results regardless of which PHP version you are using to run PHP CodeSniffer. You should get reasonably consistent results independently of the PHP version used in your test environment, though for the best results it is recommended to run the sniffs on PHP 5.4 or higher. + +PHP CodeSniffer 2.3.0 is required for 90% of the sniffs, PHP CodeSniffer 2.6.0 or later is required for full support, notices may be thrown on older versions. + +For running the sniffs on PHP 7.3, it is recommended to use PHP_CodeSniffer 3.3.1+, or, if needs be, PHP_CodeSniffer 2.9.2. +PHP_CodeSniffer < 2.9.2/3.3.1 is not fully compatible with PHP 7.3, which effectively means that PHPCompatibility can't be either. +While the sniffs will still work in _most_ cases, you can expect PHP warnings to be thrown. + +For running the sniffs on PHP 7.4, it is recommended to use PHP_CodeSniffer 3.5.0+. + +As of version 8.0.0, the PHPCompatibility standard can also be used with PHP CodeSniffer 3.x. + +As of version 9.0.0, support for PHP CodeSniffer 1.5.x and low 2.x versions < 2.3.0 has been dropped. + + +Thank you +--------- +Thanks to all [contributors](https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors) for their valuable contributions. + +Thanks to [WP Engine](https://wpengine.com) for their support on the PHP 7.0 sniffs. + + +:warning: Upgrading to PHPCompatibility 9.0.0 :warning: +-------- +This library has been reorganized. All sniffs have been placed in categories and a significant number of sniffs have been renamed. + +If you use the complete `PHPCompatibility` standard without `exclude` directives in a custom ruleset and do not (yet) use the new-style PHP_CodeSniffer annotation as introduced in [PHP_CodeSniffer 3.2.0](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.2.0), this will have no noticeable effect and everything should work as before. + +However, if you do use `exclude` directives for PHPCompatibility sniffs in a custom ruleset or if you use the [new-style PHP_CodeSniffer inline annotations](https://github.com/squizlabs/PHP_CodeSniffer/releases/3.2.0), you will need to update these when upgrading. This should be a one-time only change. +The changelog contains detailed information about all the sniff renames. + +Please read the changelog for version [9.0.0](https://github.com/PHPCompatibility/PHPCompatibility/releases/tag/9.0.0) carefully before upgrading. + + +Installation in a Composer project (method 1) +------------------------------------------- + +* Add the following lines to the `require-dev` section of your `composer.json` file. + ```json + "require-dev": { + "phpcompatibility/php-compatibility": "*" + }, + "prefer-stable" : true + ``` +* Next, PHP CodeSniffer has to be informed of the location of the standard. + - If PHPCompatibility is the **_only_** external PHP CodeSniffer standard you use, you can add the following to your `composer.json` file to automatically run the necessary command: + ```json + "scripts": { + "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility", + "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility" + } + ``` + - Alternatively - and **_strongly recommended_** if you use more than one external PHP CodeSniffer standard - you can use any of the following Composer plugins to handle this for you. + + Just add the Composer plugin you prefer to the `require-dev` section of your `composer.json` file. + + * [DealerDirect/phpcodesniffer-composer-installer](https://github.com/DealerDirect/phpcodesniffer-composer-installer):"^0.5.0" + * [higidi/composer-phpcodesniffer-standards-plugin](https://github.com/higidi/composer-phpcodesniffer-standards-plugin) + * [SimplyAdmire/ComposerPlugins](https://github.com/SimplyAdmire/ComposerPlugins). This plugin *might* still work, but appears to be abandoned. + - As a last alternative in case you use a custom ruleset, _and only if you use PHP CodeSniffer version 2.6.0 or higher_, you can tell PHP CodeSniffer the path to the PHPCompatibility standard by adding the following snippet to your custom ruleset: + ```xml + + ``` +* Run `composer update --lock` to install both PHP CodeSniffer, the PHPCompatibility coding standard and - optionally - the Composer plugin. +* Verify that the PHPCompatibility standard is registered correctly by running `./vendor/bin/phpcs -i` on the command line. PHPCompatibility should be listed as one of the available standards. +* Now you can use the following command to inspect your code: + ```bash + ./vendor/bin/phpcs -p . --standard=PHPCompatibility + ``` + +Installation via a git check-out to an arbitrary directory (method 2) +----------------------- + +* Install [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) via [your preferred method](https://github.com/squizlabs/PHP_CodeSniffer#installation). + + PHP CodeSniffer offers a variety of installation methods to suit your work-flow: Composer, [PEAR](http://pear.php.net/PHP_CodeSniffer), a Phar file, zipped/tarred release archives or checking the repository out using Git. + + **Pro-tip:** Register the path to PHPCS in your system `$PATH` environment variable to make the `phpcs` command available from anywhere in your file system. +* Download the [latest PHPCompatibility release](https://github.com/PHPCompatibility/PHPCompatibility/releases) and unzip/untar it into an arbitrary directory. + + You can also choose to clone the repository using git to easily update your install regularly. +* Add the path to the directory in which you placed your copy of the PHPCompatibility repo to the PHP CodeSniffer configuration using the below command from the command line: + ```bash + phpcs --config-set installed_paths /path/to/PHPCompatibility + ``` + I.e. if you placed the `PHPCompatibility` repository in the `/my/custom/standards/PHPCompatibility` directory, you will need to add that directory to the PHP CodeSniffer [`installed_paths` configuration variable](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#setting-the-installed-standard-paths). + + **Warning**: :warning: The `installed_paths` command overwrites any previously set `installed_paths`. If you have previously set `installed_paths` for other external standards, run `phpcs --config-show` first and then run the `installed_paths` command with all the paths you need separated by comma's, i.e.: + ```bash + phpcs --config-set installed_paths /path/1,/path/2,/path/3 + ``` + + **Pro-tip:** Alternatively, in case you use a custom ruleset _and only if you use PHP CodeSniffer version 2.6.0 or higher_, you can tell PHP CodeSniffer the path to the PHPCompatibility standard(s) by adding the following snippet to your custom ruleset: + ```xml + + ``` +* Verify that the PHPCompatibility standard is registered correctly by running `phpcs -i` on the command line. PHPCompatibility should be listed as one of the available standards. +* Now you can use the following command to inspect your code: + ```bash + phpcs -p . --standard=PHPCompatibility + ``` + +Sniffing your code for compatibility with specific PHP version(s) +------------------------------ +* Run the coding standard from the command-line with `phpcs -p . --standard=PHPCompatibility`. +* By default, you will only receive notifications about deprecated and/or removed PHP features. +* To get the most out of the PHPCompatibility standard, you should specify a `testVersion` to check against. That will enable the checks for both deprecated/removed PHP features as well as the detection of code using new PHP features. + - You can run the checks for just one specific PHP version by adding `--runtime-set testVersion 5.5` to your command line command. + - You can also specify a range of PHP versions that your code needs to support. In this situation, compatibility issues that affect any of the PHP versions in that range will be reported: `--runtime-set testVersion 5.3-5.5`. + - As of PHPCompatibility 7.1.3, you can omit one part of the range if you want to support everything above or below a particular version, i.e. use `--runtime-set testVersion 7.0-` to run all the checks for PHP 7.0 and above. +* By default the report will be sent to the console, if you want to save the report to a file, add the following to the command line command: `--report-full=path/to/report-file`. + For more information and other reporting options, check the [PHP CodeSniffer wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Reporting). + + +### Using a framework/CMS/polyfill specific ruleset + +As of mid 2018, a limited set of framework/CMS specific rulesets is available. These rulesets are hosted in their own repositories. +* `PHPCompatibilityJoomla` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityJoomla) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-joomla) +* `PHPCompatibilityWP` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityWP) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) + +Since the autumn of 2018, there are also a number of PHP polyfill specific rulesets available: +* `PHPCompatibilityPasswordCompat` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityPasswordCompat) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-passwordcompat): accounts for @ircmaxell's [`password_compat`](https://github.com/ircmaxell/password_compat) polyfill library. +* `PHPCompatibilityParagonie` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityParagonie) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie): contains two rulesets which account for the Paragonie [`random_compat`](https://github.com/paragonie/random_compat) and [`sodium_compat`](https://github.com/paragonie/sodium_compat) polyfill libraries respectively. +* `PHPCompatibilitySymfony` [GitHub](https://github.com/PHPCompatibility/PHPCompatibilitySymfony) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-symfony): contains a number of rulesets which account for various PHP polyfill libraries offered by the Symfony project. For more details about the available rulesets, please check out the [README of the PHPCompatibilitySymfony](https://github.com/PHPCompatibility/PHPCompatibilitySymfony/blob/master/README.md) repository. + +If you want to make sure you have all PHPCompatibility rulesets available at any time, you can use the `PHPCompatibilityAll` package [GitHub](https://github.com/PHPCompatibility/PHPCompatibilityAll) | [Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-all). + +**IMPORTANT:** Framework/CMS/Polyfill specific rulesets do not set the minimum PHP version for your project, so you will still need to pass a `testVersion` to get the most accurate results. + + +Using a custom ruleset +------------------------------ +Like with any PHP CodeSniffer standard, you can add PHPCompatibility to a custom PHP CodeSniffer ruleset. + +```xml + + + My rules for PHP CodeSniffer + + + + + + + + +``` + +You can also set the `testVersion` from within the ruleset: +```xml + + +``` + +Other advanced options, such as changing the message type or severity of select sniffs, as described in the [PHPCS Annotated ruleset](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml) wiki page are, of course, also supported. + +### `testVersion` in the ruleset versus command-line + +In PHPCS 3.2.0 and lower, once you set the `testVersion` in the ruleset, you could not overrule it from the command-line anymore. +Starting with PHPCS 3.3.0, a `testVersion` set via the command-line will overrule the `testVersion` in the ruleset. + +This allows for more flexibility when, for instance, your project needs to comply with PHP `5.5-`, but you have a bootstrap file which needs to be compatible with PHP `5.2-`. + + +### PHPCompatibility specific options + +At this moment, there is one sniff which has a property which can be set via the ruleset. More custom properties may become available in the future. + +The `PHPCompatibility.Extensions.RemovedExtensions` sniff checks for removed extensions based on the function prefix used for these extensions. +This might clash with userland functions using the same function prefix. + +To whitelist userland functions, you can pass a comma-delimited list of function names to the sniff. +```xml + + + + + + +``` + +This property was added in PHPCompatibility version 7.0.1. +As of PHPCompatibility version 8.0.0, this custom property is only supported in combination with PHP CodeSniffer > 2.6.0 due to an upstream bug (which was fixed in PHPCS 2.6.0). + +Projects extending PHPCompatibility +-------------------------------------- +There are hundreds of public projects using PHPCompatibility or extending on top of it. A short list of some that you might know or have a look at : +* [adamculp/php-code-quality](https://github.com/adamculp/php-code-quality) - a Docker image doing a lot of code quality checks +* [VFAC/PHP7Compatibility](https://vfac.fr/projects/php7compatibility) - a Docker container to check PHP7 Compatibility +* [grumphp-php-compatibility](https://github.com/wunderio/grumphp-php-compatibility) - A plugin for [GrumPHP](https://github.com/phpro/grumphp) +* PHPCompatibility Checker WordPress plugin : [Wordpress site](https://wordpress.org/plugins/php-compatibility-checker/) and [Github](https://github.com/wpengine/phpcompat/) +* [WordPress Tide project](https://wptide.org/) +* [PHPStorm has built-in support for PHPCompatibility](https://www.jetbrains.com/help/phpstorm/using-php-code-sniffer.html#788c81b6) + +Contributing +------- +Contributions are very welcome. Please read the [CONTRIBUTING](.github/CONTRIBUTING.md) documentation to get started. + +License +------- +This code is released under the GNU Lesser General Public License (LGPL). For more information, visit http://www.gnu.org/copyleft/lesser.html diff --git a/kirki-composer/phpcompatibility/php-compatibility/composer.json b/kirki-composer/phpcompatibility/php-compatibility/composer.json new file mode 100644 index 000000000..38fbe6370 --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/composer.json @@ -0,0 +1,44 @@ +{ + "name" : "phpcompatibility/php-compatibility", + "description" : "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "type" : "phpcodesniffer-standard", + "keywords" : [ "compatibility", "phpcs", "standards" ], + "homepage" : "http://techblog.wimgodden.be/tag/codesniffer/", + "license" : "LGPL-3.0-or-later", + "authors" : [ { + "name" : "Wim Godden", + "role" : "lead", + "homepage" : "https://github.com/wimg" + }, + { + "name" : "Juliette Reinders Folmer", + "role" : "lead", + "homepage" : "https://github.com/jrfnl" + }, + { + "name" : "Contributors", + "homepage" : "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } ], + "support" : { + "issues" : "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source" : "https://github.com/PHPCompatibility/PHPCompatibility" + }, + "require" : { + "php" : ">=5.3", + "squizlabs/php_codesniffer" : "^2.3 || ^3.0.2" + }, + "require-dev" : { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "suggest" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "scripts" : { + "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths ../../..", + "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths ../../.." + } +} diff --git a/kirki-composer/phpcompatibility/php-compatibility/phpunit-bootstrap.php b/kirki-composer/phpcompatibility/php-compatibility/phpunit-bootstrap.php new file mode 100644 index 000000000..f66ec0cfa --- /dev/null +++ b/kirki-composer/phpcompatibility/php-compatibility/phpunit-bootstrap.php @@ -0,0 +1,86 @@ +=') + && class_exists('PHPUnit_Framework_TestCase') === false +) { + class_alias('PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase'); +} + +require_once __DIR__ . $ds . 'PHPCompatibility' . $ds . 'Tests' . $ds . 'BaseSniffTest.php'; +require_once __DIR__ . $ds . 'PHPCompatibility' . $ds . 'Util' . $ds . 'Tests' . $ds . 'CoreMethodTestFrame.php'; +unset($ds, $phpcsDir, $vendorDir); diff --git a/kirki-composer/phpcompatibility/phpcompatibility-paragonie/LICENSE b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/LICENSE new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/LICENSE @@ -0,0 +1,165 @@ + 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. diff --git a/kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml new file mode 100644 index 000000000..e67a12e0b --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieRandomCompat/ruleset.xml @@ -0,0 +1,40 @@ + + + PHPCompatibility ruleset for PHP_CodeSniffer which accounts for polyfills provided by the Paragonie random_compat library. + + + + + + + + + + + + + + + + + + + /random_compat/lib/byte_safe_strings\.php$ + + + /random_compat/lib/random_bytes_dev_urandom\.php$ + + + /random_compat/lib/random_bytes_mcrypt\.php$ + + + /random_compat/lib/random_bytes_mcrypt\.php$ + + + /random_compat/lib/random_bytes_mcrypt\.php$ + + + /random_compat/lib/random_bytes_libsodium\.php$ + + + diff --git a/kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml new file mode 100644 index 000000000..e08fea53a --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/PHPCompatibilityParagonieSodiumCompat/ruleset.xml @@ -0,0 +1,244 @@ + + + PHPCompatibility ruleset for PHP_CodeSniffer which accounts for polyfills provided by the Paragonie sodium_compat library. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /sodium_compat/autoload\.php$ + + + /sodium_compat/src/Core(32)?/Curve25519/Fe\.php$ + + + /sodium_compat/src/Core/Util\.php$ + + + /sodium_compat/src/Core/Util\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Compat\.php$ + + + /sodium_compat/src/Core/Util\.php$ + + + diff --git a/kirki-composer/phpcompatibility/phpcompatibility-paragonie/README.md b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/README.md new file mode 100644 index 000000000..ed3e4d754 --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/README.md @@ -0,0 +1,143 @@ +[![Latest Stable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-paragonie/v/stable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie) +[![Latest Unstable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-paragonie/v/unstable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie) +[![License](https://poser.pugx.org/phpcompatibility/phpcompatibility-paragonie/license.png)](https://github.com/PHPCompatibility/PHPCompatibilityParagonie/blob/master/LICENSE) +[![Build Status](https://github.com/PHPCompatibility/PHPCompatibilityParagonie/workflows/CI/badge.svg?branch=master)](https://github.com/PHPCompatibility/PHPCompatibilityParagonie/actions) + +# PHPCompatibilityParagonie + +Using PHPCompatibilityParagonie, you can analyse the codebase of a project using either of the Paragonie polyfills, for PHP cross-version compatibility. + + +## What's in this repo ? + +Two rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries. + +These rulesets prevent false positives from the [PHPCompatibility standard](https://github.com/PHPCompatibility/PHPCompatibility) by excluding back-fills and poly-fills which are provided by those libraries. + +Paragonie Polyfill Library | Corresponding PHPCompatibility Ruleset | Includes +--- | --- | --- +[`random_compat`](https://github.com/paragonie/random_compat) | `PHPCompatibilityParagonieRandomCompat` +[`sodium_compat`](https://github.com/paragonie/sodium_compat) | `PHPCompatibilityParagonieSodiumCompat` | `PHPCompatibilityParagonieRandomCompat` + +> Note: +> As the `sodium_compat` library has `random_compat` [as a dependency](https://github.com/paragonie/sodium_compat/blob/master/composer.json), the `PHPCompatibilityParagonieSodiumCompat` ruleset includes the `PHPCompatibilityParagonieRandomCompat` ruleset. +> +> In practice, this means that if your project uses both libraries, you just need to use the `PHPCompatibilityParagonieSodiumCompat` ruleset to prevent false positives from both. + + +## Requirements + +* [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). + * PHP 5.3+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 2.3.0+. + * PHP 5.4+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 3.0.2+. + + Use the latest stable release of PHP_CodeSniffer for the best results. + The minimum _recommended_ version of PHP_CodeSniffer is version 2.6.0. +* [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) 9.0.0+. + + +## Installation instructions + +The only supported installation method is via [Composer](https://getcomposer.org/). + +If you don't have a Composer plugin installed to manage the `installed_paths` setting for PHP_CodeSniffer, run the following from the command-line: +```bash +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +composer require --dev dealerdirect/phpcodesniffer-composer-installer:"^0.7" phpcompatibility/phpcompatibility-paragonie:"*" +``` + +If you already have a Composer PHP_CodeSniffer plugin installed, run: +```bash +composer require --dev phpcompatibility/phpcompatibility-paragonie:"*" +``` + +Next, run: +```bash +vendor/bin/phpcs -i +``` +If all went well, you will now see that the `PHPCompatibility`, `PHPCompatibilityParagonieRandomCompat` and `PHPCompatibilityParagonieSodiumCompat` standards are installed for PHP_CodeSniffer. + + +## How to use + +Now you can use the following commands to inspect the code in your project for PHP cross-version compatibility: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieRandomCompat + +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieSodiumCompat +``` + +By default, you will only receive notifications about deprecated and/or removed PHP features. + +To get the most out of the PHPCompatibilityParagonie rulesets, you should specify a `testVersion` to check against. That will enable the checks for both deprecated/removed PHP features as well as the detection of code using new PHP features. + +For example: +```bash +# For a project which should be compatible with PHP 5.3 up to and including PHP 7.0: +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieRandomCompat --runtime-set testVersion 5.3-7.0 + +# For a project which should be compatible with PHP 5.4 and higher: +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieSodiumCompat --runtime-set testVersion 5.4- +``` + +For more detailed information about setting the `testVersion`, see the README of the generic [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions) standard. + + +### Testing PHP files only + +By default PHP_CodeSniffer will analyse PHP, JavaScript and CSS files. As the PHPCompatibility sniffs only target PHP code, you can make the run slightly faster by telling PHP_CodeSniffer to only check PHP files, like so: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityParagonieRandomCompat --extensions=php --runtime-set testVersion 5.3- +``` + +## License + +All code within the PHPCompatibility organisation is released under the GNU Lesser General Public License (LGPL). For more information, visit https://www.gnu.org/copyleft/lesser.html + + +## Changelog + +### 1.3.2 - 2022-10-25 + +- README: Updated the installation instructions for [compatibility with Composer >= 2.2][composer22announce]. +- Composer: The package will now identify itself as a static analysis tool. Thanks [@GaryJones]! +- Other housekeeping and minor documentation updates. + +[composer22announce]: https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution + +### 1.3.1 - 2021-02-15 + +- The recommended version of the [Composer PHPCS plugin] is now `^0.7.0`, which offers compatibility with Composer 2.0. +- The rulesets are now also tested against PHP 7.4 and 8.0. + Note: full PHP 7.4 support is only available in combination with PHP_CodeSniffer >= 3.5.6. + Note: runtime PHP 8.0 support is only available in combination with PHP_CodeSniffer >= 3.5.7, full support is expected in PHP_CodeSniffer 3.6.0. + +### 1.3.0 - 2019-11-04 + +* Ruleset update for full compatibility with version [`1.12.0` of `sodium_compat`](https://github.com/paragonie/sodium_compat/releases/tag/v1.12.0). + +### 1.2.0 - 2019-10-16 + +* Ruleset update for full compatibility with version [`1.11.0` of `sodium_compat`](https://github.com/paragonie/sodium_compat/releases/tag/v1.11.0). + +### 1.1.0 - 2019-08-29 + +* The `PHPCompatibilityParagonieSodiumCompat` ruleset has been updated to account for the latest changes in the `sodium_compat` polyfill. +* Prevent false positives when the ruleset is run over the code of the `sodium_compat` polyfill itself. +* Composer: The recommended version of the [Composer PHPCS plugin] has been upped to `^0.5.0`. +* CI: Improved integration test for the `SodiumCompat` ruleset. +* CI: Added early warning system for false positives due to changes in the polyfill libraries themselves. + +### 1.0.1 - 2018-12-16 + +* Prevent false positives when the ruleset is run over the code of the `random_compat` polyfill itself. +* The rulesets are now also tested against PHP 7.3. + Note: full PHP 7.3 support is only available in combination with PHP_CodeSniffer 2.9.2 or 3.3.1+ due to an incompatibility within PHP_CodeSniffer itself. + +### 1.0.0 - 2018-10-07 + +Initial release of PHPCompatibilityParagonie containing rulesets covering the `random_compat` and `sodium_compat` polyfill libraries. + +[Composer PHPCS plugin]: https://github.com/PHPCSStandards/composer-installer/ + +[@GaryJones]: https://github.com/GaryJones diff --git a/kirki-composer/phpcompatibility/phpcompatibility-paragonie/composer.json b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/composer.json new file mode 100644 index 000000000..27a96521e --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-paragonie/composer.json @@ -0,0 +1,38 @@ +{ + "name" : "phpcompatibility/phpcompatibility-paragonie", + "description" : "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "type" : "phpcodesniffer-standard", + "keywords" : [ "compatibility", "phpcs", "standards", "static analysis", "paragonie", "polyfill" ], + "homepage" : "http://phpcompatibility.com/", + "license" : "LGPL-3.0-or-later", + "authors" : [ { + "name" : "Wim Godden", + "role" : "lead" + }, + { + "name" : "Juliette Reinders Folmer", + "role" : "lead" + } ], + "support" : { + "issues" : "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "source" : "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "require" : { + "phpcompatibility/php-compatibility" : "^9.0" + }, + "require-dev" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" + }, + "suggest" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "prefer-stable" : true +} diff --git a/kirki-composer/phpcompatibility/phpcompatibility-wp/LICENSE b/kirki-composer/phpcompatibility/phpcompatibility-wp/LICENSE new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-wp/LICENSE @@ -0,0 +1,165 @@ + 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. diff --git a/kirki-composer/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml b/kirki-composer/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml new file mode 100644 index 000000000..4d92d8b2d --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-wp/PHPCompatibilityWP/ruleset.xml @@ -0,0 +1,82 @@ + + + WordPress specific ruleset which checks for PHP cross version compatibility. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/phpcompatibility/phpcompatibility-wp/README.md b/kirki-composer/phpcompatibility/phpcompatibility-wp/README.md new file mode 100644 index 000000000..55d66b91e --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-wp/README.md @@ -0,0 +1,135 @@ +[![Latest Stable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-wp/v/stable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) +[![Latest Unstable Version](https://poser.pugx.org/phpcompatibility/phpcompatibility-wp/v/unstable.png)](https://packagist.org/packages/phpcompatibility/phpcompatibility-wp) +[![License](https://poser.pugx.org/phpcompatibility/phpcompatibility-wp/license.png)](https://github.com/PHPCompatibility/PHPCompatibilityWP/blob/master/LICENSE) +[![Build Status](https://github.com/PHPCompatibility/PHPCompatibilityWP/workflows/CI/badge.svg?branch=master)](https://github.com/PHPCompatibility/PHPCompatibilityWP/actions) + +# PHPCompatibilityWP + +Using PHPCompatibilityWP, you can analyse the codebase of a WordPress-based project for PHP cross-version compatibility. + + +## What's in this repo ? + +A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects based on the WordPress CMS. + +This WordPress specific ruleset prevents false positives from the [PHPCompatibility standard](https://github.com/PHPCompatibility/PHPCompatibility) by excluding back-fills and poly-fills which are provided by WordPress. + + +## Requirements + +* [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). + * PHP 5.3+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 2.3.0+. + * PHP 5.4+ for use with [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) 3.0.2+. + + Use the latest stable release of PHP_CodeSniffer for the best results. + The minimum _recommended_ version of PHP_CodeSniffer is version 2.6.0. +* [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) 9.0.0+. +* [PHPCompatibilityParagonie](https://github.com/PHPCompatibility/PHPCompatibilityParagonie) 1.0.0+. + + +## Installation instructions + +The only supported installation method is via [Composer](https://getcomposer.org/). + +If you don't have a Composer plugin installed to manage the `installed_paths` setting for PHP_CodeSniffer, run the following from the command-line: +```bash +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +composer require --dev dealerdirect/phpcodesniffer-composer-installer:"^0.7" phpcompatibility/phpcompatibility-wp:"*" +``` + +If you already have a Composer PHP_CodeSniffer plugin installed, run: +```bash +composer require --dev phpcompatibility/phpcompatibility-wp:"*" +``` + +Next, run: +```bash +vendor/bin/phpcs -i +``` +If all went well, you will now see that the `PHPCompatibility`, `PHPCompatibilityWP` and some more PHPCompatibility standards are installed for PHP_CodeSniffer. + + +## How to use + +Now you can use the following command to inspect your code: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityWP +``` + +By default, you will only receive notifications about deprecated and/or removed PHP features. + +To get the most out of the PHPCompatibilityWP standard, you should specify a `testVersion` to check against. That will enable the checks for both deprecated/removed PHP features as well as the detection of code using new PHP features. + +The minimum PHP requirement of the WordPress project up to WP 5.1 was 5.2.4. As of WP 5.2 it will be PHP 5.6.20. If you want to enforce this, either add `--runtime-set testVersion 5.6-` to your command-line command or add `` to your [custom ruleset](https://github.com/PHPCompatibility/PHPCompatibility#using-a-custom-ruleset). + +For example: +```bash +# For a project which should be compatible with PHP 5.6 and higher: +./vendor/bin/phpcs -p . --standard=PHPCompatibilityWP --runtime-set testVersion 5.6- +``` + +For more detailed information about setting the `testVersion`, see the README of the generic [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions) standard. + + +### Testing PHP files only + +By default PHP_CodeSniffer will analyse PHP, JavaScript and CSS files. As the PHPCompatibility sniffs only target PHP code, you can make the run slightly faster by telling PHP_CodeSniffer to only check PHP files, like so: +```bash +./vendor/bin/phpcs -p . --standard=PHPCompatibilityWP --extensions=php --runtime-set testVersion 5.6- +``` + +## License + +All code within the PHPCompatibility organisation is released under the GNU Lesser General Public License (LGPL). For more information, visit https://www.gnu.org/copyleft/lesser.html + + +## Changelog + +### 2.1.4 - 2022-10-24 + +- Composer: The package will now identify itself as a static analysis tool. Thanks [@GaryJones]! +- Other housekeeping and minor documentation updates. + +### 2.1.3 - 2021-12-31 + +- Ruleset: Updated for compatibility with WordPress 5.9. +- README: Updated the installation instructions for [compatibility with Composer >= 2.2][composer22announce]. +- Minor housekeeping. + +[composer22announce]: https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution + +### 2.1.2 - 2021-07-21 + +- Ruleset: Updated for compatibility with WordPress 5.8. +- Documentation: improved installation instructions. Props [Andy Fragen](https://github.com/afragen). + +### 2.1.1 - 2021-02-15 + +- The recommended version of the [Composer PHPCS plugin] is now `^0.7.0`, which offers compatibility with Composer 2.0. +- The ruleset is now also tested against PHP 7.4 and 8.0. + Note: full PHP 7.4 support is only available in combination with PHP_CodeSniffer >= 3.5.6. + Note: runtime PHP 8.0 support is only available in combination with PHP_CodeSniffer >= 3.5.7, full support is expected in PHP_CodeSniffer 3.6.0. + +### 2.1.0 - 2019-08-29 + +- Ruleset: Updated for the Sodium_Compat polyfill which is included in WordPress 5.2. +- Composer: The recommended version of the [Composer PHPCS plugin] has been upped to `^0.5.0`. +- Documentation: Updated the ruleset inline documentation and the Readme to reflect the change in minimum PHP requirements for WordPress as of WP 5.2. +- Documentation: Updated the ruleset inline documentation to include information on when each polyfill was added to/removed from WordPress. +- CI: The rulesets are now also tested against PHP 7.3. + Note: full PHP 7.3 support is only available in combination with PHP_CodeSniffer 2.9.2 or 3.3.1+ due to an incompatibility within PHP_CodeSniffer itself. + +### 2.0.0 - 2018-10-07 + +- Ruleset: Updated for compatibility with PHPCompatibility 9.0+. +- Composer: Added dependency for a dedicated polyfill-based PHPCompatibility ruleset. +- CI: Added a test for the ruleset. +- Readme: Removed the installation instructions for a non-Composer based install. + +### 1.0.0 - 2018-07-17 + +Initial release of the PHPCompatibilityWP ruleset. + +[Composer PHPCS plugin]: https://github.com/PHPCSStandards/composer-installer/ + +[@GaryJones]: https://github.com/GaryJones diff --git a/kirki-composer/phpcompatibility/phpcompatibility-wp/composer.json b/kirki-composer/phpcompatibility/phpcompatibility-wp/composer.json new file mode 100644 index 000000000..2132398a8 --- /dev/null +++ b/kirki-composer/phpcompatibility/phpcompatibility-wp/composer.json @@ -0,0 +1,37 @@ +{ + "name" : "phpcompatibility/phpcompatibility-wp", + "description" : "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "type" : "phpcodesniffer-standard", + "keywords" : [ "compatibility", "phpcs", "standards", "static analysis", "wordpress" ], + "homepage" : "http://phpcompatibility.com/", + "license" : "LGPL-3.0-or-later", + "authors" : [ { + "name" : "Wim Godden", + "role" : "lead" + }, + { + "name" : "Juliette Reinders Folmer", + "role" : "lead" + } ], + "support" : { + "issues" : "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "source" : "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "require" : { + "phpcompatibility/php-compatibility" : "^9.0", + "phpcompatibility/phpcompatibility-paragonie" : "^1.0" + }, + "require-dev" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7" + }, + "suggest" : { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "prefer-stable" : true +} diff --git a/kirki-composer/squizlabs/php_codesniffer/CONTRIBUTING.md b/kirki-composer/squizlabs/php_codesniffer/CONTRIBUTING.md new file mode 100644 index 000000000..5cc736353 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/CONTRIBUTING.md @@ -0,0 +1,13 @@ +Contributing +------------- + +Before you contribute code to PHP\_CodeSniffer, please make sure it conforms to the PHPCS coding standard and that the PHP\_CodeSniffer unit tests still pass. The easiest way to contribute is to work on a checkout of the repository, or your own fork, rather than an installed PEAR version. If you do this, you can run the following commands to check if everything is ready to submit: + + cd PHP_CodeSniffer + php bin/phpcs + +Which should display no coding standard errors. And then: + + phpunit + +Which should give you no failures or errors. You can ignore any skipped tests as these are for external tools. diff --git a/kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf b/kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf new file mode 100644 index 000000000..7547cca3d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf @@ -0,0 +1,5 @@ + '../../phpcompatibility/php-compatibility,../../phpcompatibility/phpcompatibility-paragonie,../../phpcompatibility/phpcompatibility-wp,../../wp-coding-standards/wpcs,../../wptrt/wpthemereview', +); +?> \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf.dist b/kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf.dist new file mode 100644 index 000000000..f95058faa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/CodeSniffer.conf.dist @@ -0,0 +1,9 @@ + 'PSR2', + 'report_format' => 'summary', + 'show_warnings' => '0', + 'show_progress' => '1', + 'report_width' => '120', +); +?> diff --git a/kirki-composer/squizlabs/php_codesniffer/README.md b/kirki-composer/squizlabs/php_codesniffer/README.md new file mode 100644 index 000000000..859de432c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/README.md @@ -0,0 +1,134 @@ +## About + +PHP_CodeSniffer is a set of two PHP scripts; the main `phpcs` script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second `phpcbf` script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent. + +[![Build Status](https://github.com/squizlabs/PHP_CodeSniffer/workflows/Validate/badge.svg?branch=master)](https://github.com/squizlabs/PHP_CodeSniffer/actions) +[![Build Status](https://github.com/squizlabs/PHP_CodeSniffer/workflows/Test/badge.svg?branch=master)](https://github.com/squizlabs/PHP_CodeSniffer/actions) +[![Code consistency](http://squizlabs.github.io/PHP_CodeSniffer/analysis/squizlabs/PHP_CodeSniffer/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/squizlabs/PHP_CodeSniffer) +[![Join the chat at https://gitter.im/squizlabs/PHP_CodeSniffer](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/squizlabs/PHP_CodeSniffer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Requirements + +PHP_CodeSniffer requires PHP version 5.4.0 or greater, although individual sniffs may have additional requirements such as external applications and scripts. See the [Configuration Options manual page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options) for a list of these requirements. + +If you're using PHP_CodeSniffer as part of a team, or you're running it on a [CI](https://en.wikipedia.org/wiki/Continuous_integration) server, you may want to configure your project's settings [using a configuration file](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file). + + +## Installation + +The easiest way to get started with PHP_CodeSniffer is to download the Phar files for each of the commands: +``` +# Download using curl +curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar +curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar + +# Or download using wget +wget https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar +wget https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar + +# Then test the downloaded PHARs +php phpcs.phar -h +php phpcbf.phar -h +``` + +### Composer +If you use Composer, you can install PHP_CodeSniffer system-wide with the following command: +```bash +composer global require "squizlabs/php_codesniffer=*" +``` +Make sure you have the composer bin dir in your PATH. The default value is `~/.composer/vendor/bin/`, but you can check the value that you need to use by running `composer global config bin-dir --absolute`. + +Or alternatively, include a dependency for `squizlabs/php_codesniffer` in your `composer.json` file. For example: + +```json +{ + "require-dev": { + "squizlabs/php_codesniffer": "3.*" + } +} +``` + +You will then be able to run PHP_CodeSniffer from the vendor bin directory: +```bash +./vendor/bin/phpcs -h +./vendor/bin/phpcbf -h +``` +### Phive +If you use Phive, you can install PHP_CodeSniffer as a project tool using the following commands: +```bash +phive install phpcs +phive install phpcbf +``` +You will then be able to run PHP_CodeSniffer from the tools directory: +```bash +./tools/phpcs -h +./tools/phpcbf -h +``` +### PEAR +If you use PEAR, you can install PHP_CodeSniffer using the PEAR installer. This will make the `phpcs` and `phpcbf` commands immediately available for use. To install PHP_CodeSniffer using the PEAR installer, first ensure you have [installed PEAR](http://pear.php.net/manual/en/installation.getting.php) and then run the following command: +```bash +pear install PHP_CodeSniffer +``` +### Git Clone +You can also download the PHP_CodeSniffer source and run the `phpcs` and `phpcbf` commands directly from the Git clone: +```bash +git clone https://github.com/squizlabs/PHP_CodeSniffer.git +cd PHP_CodeSniffer +php bin/phpcs -h +php bin/phpcbf -h +``` +## Getting Started + +The default coding standard used by PHP_CodeSniffer is the PEAR coding standard. To check a file against the PEAR coding standard, simply specify the file's location: +```bash +phpcs /path/to/code/myfile.php +``` +Or if you wish to check an entire directory you can specify the directory location instead of a file. +```bash +phpcs /path/to/code-directory +``` +If you wish to check your code against the PSR-12 coding standard, use the `--standard` command line argument: +```bash +phpcs --standard=PSR12 /path/to/code-directory +``` + +If PHP_CodeSniffer finds any coding standard errors, a report will be shown after running the command. + +Full usage information and example reports are available on the [usage page](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). + +## Documentation + +The documentation for PHP_CodeSniffer is available on the [Github wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki). + +## Issues + +Bug reports and feature requests can be submitted on the [Github Issue Tracker](https://github.com/squizlabs/PHP_CodeSniffer/issues). + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for information. + +## Versioning + +PHP_CodeSniffer uses a `MAJOR.MINOR.PATCH` version number format. + +The `MAJOR` version is incremented when: +- backwards-incompatible changes are made to how the `phpcs` or `phpcbf` commands are used, or +- backwards-incompatible changes are made to the `ruleset.xml` format, or +- backwards-incompatible changes are made to the API used by sniff developers, or +- custom PHP_CodeSniffer token types are removed, or +- existing sniffs are removed from PHP_CodeSniffer entirely + +The `MINOR` version is incremented when: +- new backwards-compatible features are added to the `phpcs` and `phpcbf` commands, or +- backwards-compatible changes are made to the `ruleset.xml` format, or +- backwards-compatible changes are made to the API used by sniff developers, or +- new sniffs are added to an included standard, or +- existing sniffs are removed from an included standard + +> NOTE: Backwards-compatible changes to the API used by sniff developers will allow an existing sniff to continue running without producing fatal errors but may not result in the sniff reporting the same errors as it did previously without changes being required. + +The `PATCH` version is incremented when: +- backwards-compatible bug fixes are made + +> NOTE: As PHP_CodeSniffer exists to report and fix issues, most bugs are the result of coding standard errors being incorrectly reported or coding standard errors not being reported when they should be. This means that the messages produced by PHP_CodeSniffer, and the fixes it makes, are likely to be different between PATCH versions. diff --git a/kirki-composer/squizlabs/php_codesniffer/autoload.php b/kirki-composer/squizlabs/php_codesniffer/autoload.php new file mode 100644 index 000000000..0dcf1b4c8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/autoload.php @@ -0,0 +1,342 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +if (class_exists('PHP_CodeSniffer\Autoload', false) === false) { + class Autoload + { + + /** + * The composer autoloader. + * + * @var \Composer\Autoload\ClassLoader + */ + private static $composerAutoloader = null; + + /** + * A mapping of file names to class names. + * + * @var array + */ + private static $loadedClasses = []; + + /** + * A mapping of class names to file names. + * + * @var array + */ + private static $loadedFiles = []; + + /** + * A list of additional directories to search during autoloading. + * + * This is typically a list of coding standard directories. + * + * @var string[] + */ + private static $searchPaths = []; + + + /** + * Loads a class. + * + * This method only loads classes that exist in the PHP_CodeSniffer namespace. + * All other classes are ignored and loaded by subsequent autoloaders. + * + * @param string $class The name of the class to load. + * + * @return bool + */ + public static function load($class) + { + // Include the composer autoloader if there is one, but re-register it + // so this autoloader runs before the composer one as we need to include + // all files so we can figure out what the class/interface/trait name is. + if (self::$composerAutoloader === null) { + // Make sure we don't try to load any of Composer's classes + // while the autoloader is being setup. + if (strpos($class, 'Composer\\') === 0) { + return; + } + + if (strpos(__DIR__, 'phar://') !== 0 + && @file_exists(__DIR__.'/../../autoload.php') === true + ) { + self::$composerAutoloader = include __DIR__.'/../../autoload.php'; + if (self::$composerAutoloader instanceof \Composer\Autoload\ClassLoader) { + self::$composerAutoloader->unregister(); + self::$composerAutoloader->register(); + } else { + // Something went wrong, so keep going without the autoloader + // although namespaced sniffs might error. + self::$composerAutoloader = false; + } + } else { + self::$composerAutoloader = false; + } + }//end if + + $ds = DIRECTORY_SEPARATOR; + $path = false; + + if (substr($class, 0, 16) === 'PHP_CodeSniffer\\') { + if (substr($class, 0, 22) === 'PHP_CodeSniffer\Tests\\') { + $isInstalled = !is_dir(__DIR__.$ds.'tests'); + if ($isInstalled === false) { + $path = __DIR__.$ds.'tests'; + } else { + $path = '@test_dir@'.$ds.'PHP_CodeSniffer'.$ds.'CodeSniffer'; + } + + $path .= $ds.substr(str_replace('\\', $ds, $class), 22).'.php'; + } else { + $path = __DIR__.$ds.'src'.$ds.substr(str_replace('\\', $ds, $class), 16).'.php'; + } + } + + // See if the composer autoloader knows where the class is. + if ($path === false && self::$composerAutoloader !== false) { + $path = self::$composerAutoloader->findFile($class); + } + + // See if the class is inside one of our alternate search paths. + if ($path === false) { + foreach (self::$searchPaths as $searchPath => $nsPrefix) { + $className = $class; + if ($nsPrefix !== '' && substr($class, 0, strlen($nsPrefix)) === $nsPrefix) { + $className = substr($class, (strlen($nsPrefix) + 1)); + } + + $path = $searchPath.$ds.str_replace('\\', $ds, $className).'.php'; + if (is_file($path) === true) { + break; + } + + $path = false; + } + } + + if ($path !== false && is_file($path) === true) { + self::loadFile($path); + return true; + } + + return false; + + }//end load() + + + /** + * Includes a file and tracks what class or interface was loaded as a result. + * + * @param string $path The path of the file to load. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function loadFile($path) + { + if (strpos(__DIR__, 'phar://') !== 0) { + $path = realpath($path); + if ($path === false) { + return false; + } + } + + if (isset(self::$loadedClasses[$path]) === true) { + return self::$loadedClasses[$path]; + } + + $classesBeforeLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + include $path; + + $classesAfterLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + $className = self::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + + self::$loadedClasses[$path] = $className; + self::$loadedFiles[$className] = $path; + return self::$loadedClasses[$path]; + + }//end loadFile() + + + /** + * Determine which class was loaded based on the before and after lists of loaded classes. + * + * @param array $classesBeforeLoad The classes/interfaces/traits before the file was included. + * @param array $classesAfterLoad The classes/interfaces/traits after the file was included. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function determineLoadedClass($classesBeforeLoad, $classesAfterLoad) + { + $className = null; + + $newClasses = array_diff($classesAfterLoad['classes'], $classesBeforeLoad['classes']); + if (PHP_VERSION_ID < 70400) { + $newClasses = array_reverse($newClasses); + } + + // Since PHP 7.4 get_declared_classes() does not guarantee any order, making + // it impossible to use order to determine which is the parent an which is the child. + // Let's reduce the list of candidates by removing all the classes known to be "parents". + // That way, at the end, only the "main" class just included will remain. + $newClasses = array_reduce( + $newClasses, + function ($remaining, $current) { + return array_diff($remaining, class_parents($current)); + }, + $newClasses + ); + + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + + if ($className === null) { + $newClasses = array_reverse(array_diff($classesAfterLoad['interfaces'], $classesBeforeLoad['interfaces'])); + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + } + + if ($className === null) { + $newClasses = array_reverse(array_diff($classesAfterLoad['traits'], $classesBeforeLoad['traits'])); + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + } + + return $className; + + }//end determineLoadedClass() + + + /** + * Adds a directory to search during autoloading. + * + * @param string $path The path to the directory to search. + * @param string $nsPrefix The namespace prefix used by files under this path. + * + * @return void + */ + public static function addSearchPath($path, $nsPrefix='') + { + self::$searchPaths[$path] = rtrim(trim((string) $nsPrefix), '\\'); + + }//end addSearchPath() + + + /** + * Retrieve the namespaces and paths registered by external standards. + * + * @return array + */ + public static function getSearchPaths() + { + return self::$searchPaths; + + }//end getSearchPaths() + + + /** + * Gets the class name for the given file path. + * + * @param string $path The name of the file. + * + * @throws \Exception If the file path has not been loaded. + * @return string + */ + public static function getLoadedClassName($path) + { + if (isset(self::$loadedClasses[$path]) === false) { + throw new \Exception("Cannot get class name for $path; file has not been included"); + } + + return self::$loadedClasses[$path]; + + }//end getLoadedClassName() + + + /** + * Gets the file path for the given class name. + * + * @param string $class The name of the class. + * + * @throws \Exception If the class name has not been loaded + * @return string + */ + public static function getLoadedFileName($class) + { + if (isset(self::$loadedFiles[$class]) === false) { + throw new \Exception("Cannot get file name for $class; class has not been included"); + } + + return self::$loadedFiles[$class]; + + }//end getLoadedFileName() + + + /** + * Gets the mapping of file names to class names. + * + * @return array + */ + public static function getLoadedClasses() + { + return self::$loadedClasses; + + }//end getLoadedClasses() + + + /** + * Gets the mapping of class names to file names. + * + * @return array + */ + public static function getLoadedFiles() + { + return self::$loadedFiles; + + }//end getLoadedFiles() + + + }//end class + + // Register the autoloader before any existing autoloaders to ensure + // it gets a chance to hear about every autoload request, and record + // the file and class name for it. + spl_autoload_register(__NAMESPACE__.'\Autoload::load', true, true); +}//end if diff --git a/kirki-composer/squizlabs/php_codesniffer/bin/phpcbf b/kirki-composer/squizlabs/php_codesniffer/bin/phpcbf new file mode 100644 index 000000000..45b43f432 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/bin/phpcbf @@ -0,0 +1,19 @@ +#!/usr/bin/env php + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (is_file(__DIR__.'/../autoload.php') === true) { + include_once __DIR__.'/../autoload.php'; +} else { + include_once 'PHP/CodeSniffer/autoload.php'; +} + +$runner = new PHP_CodeSniffer\Runner(); +$exitCode = $runner->runPHPCBF(); +exit($exitCode); diff --git a/kirki-composer/squizlabs/php_codesniffer/bin/phpcbf.bat b/kirki-composer/squizlabs/php_codesniffer/bin/phpcbf.bat new file mode 100644 index 000000000..5b07a7d92 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/bin/phpcbf.bat @@ -0,0 +1,12 @@ +@echo off +REM PHP Code Beautifier and Fixer fixes violations of a defined coding standard. +REM +REM @author Greg Sherwood +REM @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) +REM @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + +if "%PHP_PEAR_PHP_BIN%" neq "" ( + set PHPBIN=%PHP_PEAR_PHP_BIN% +) else set PHPBIN=php + +"%PHPBIN%" "%~dp0\phpcbf" %* diff --git a/kirki-composer/squizlabs/php_codesniffer/bin/phpcs b/kirki-composer/squizlabs/php_codesniffer/bin/phpcs new file mode 100644 index 000000000..52d28cdf1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/bin/phpcs @@ -0,0 +1,19 @@ +#!/usr/bin/env php + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (is_file(__DIR__.'/../autoload.php') === true) { + include_once __DIR__.'/../autoload.php'; +} else { + include_once 'PHP/CodeSniffer/autoload.php'; +} + +$runner = new PHP_CodeSniffer\Runner(); +$exitCode = $runner->runPHPCS(); +exit($exitCode); diff --git a/kirki-composer/squizlabs/php_codesniffer/bin/phpcs.bat b/kirki-composer/squizlabs/php_codesniffer/bin/phpcs.bat new file mode 100644 index 000000000..9f9be7203 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/bin/phpcs.bat @@ -0,0 +1,12 @@ +@echo off +REM PHP_CodeSniffer detects violations of a defined coding standard. +REM +REM @author Greg Sherwood +REM @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) +REM @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + +if "%PHP_PEAR_PHP_BIN%" neq "" ( + set PHPBIN=%PHP_PEAR_PHP_BIN% +) else set PHPBIN=php + +"%PHPBIN%" "%~dp0\phpcs" %* diff --git a/kirki-composer/squizlabs/php_codesniffer/composer.json b/kirki-composer/squizlabs/php_codesniffer/composer.json new file mode 100644 index 000000000..7605a5df9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/composer.json @@ -0,0 +1,40 @@ +{ + "name": "squizlabs/php_codesniffer", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "type": "library", + "keywords": [ + "phpcs", + "standards" + ], + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki", + "source": "https://github.com/squizlabs/PHP_CodeSniffer" + }, + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "require": { + "php": ">=5.4.0", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "ext-simplexml": "*" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ] +} diff --git a/kirki-composer/squizlabs/php_codesniffer/licence.txt b/kirki-composer/squizlabs/php_codesniffer/licence.txt new file mode 100644 index 000000000..9f95b6771 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/licence.txt @@ -0,0 +1,24 @@ +Copyright (c) 2012, Squiz Pty Ltd (ABN 77 084 670 600) +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 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 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. diff --git a/kirki-composer/squizlabs/php_codesniffer/phpcs.xsd b/kirki-composer/squizlabs/php_codesniffer/phpcs.xsd new file mode 100644 index 000000000..d93dd868c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/phpcs.xsd @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Config.php b/kirki-composer/squizlabs/php_codesniffer/src/Config.php new file mode 100644 index 000000000..915ad0030 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Config.php @@ -0,0 +1,1704 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; + +/** + * Stores the configuration used to run PHPCS and PHPCBF. + * + * @property string[] $files The files and directories to check. + * @property string[] $standards The standards being used for checking. + * @property int $verbosity How verbose the output should be. + * 0: no unnecessary output + * 1: basic output for files being checked + * 2: ruleset and file parsing output + * 3: sniff execution output + * @property bool $interactive Enable interactive checking mode. + * @property bool $parallel Check files in parallel. + * @property bool $cache Enable the use of the file cache. + * @property bool $cacheFile A file where the cache data should be written + * @property bool $colors Display colours in output. + * @property bool $explain Explain the coding standards. + * @property bool $local Process local files in directories only (no recursion). + * @property bool $showSources Show sniff source codes in report output. + * @property bool $showProgress Show basic progress information while running. + * @property bool $quiet Quiet mode; disables progress and verbose output. + * @property bool $annotations Process phpcs: annotations. + * @property int $tabWidth How many spaces each tab is worth. + * @property string $encoding The encoding of the files being checked. + * @property string[] $sniffs The sniffs that should be used for checking. + * If empty, all sniffs in the supplied standards will be used. + * @property string[] $exclude The sniffs that should be excluded from checking. + * If empty, all sniffs in the supplied standards will be used. + * @property string[] $ignored Regular expressions used to ignore files and folders during checking. + * @property string $reportFile A file where the report output should be written. + * @property string $generator The documentation generator to use. + * @property string $filter The filter to use for the run. + * @property string[] $bootstrap One of more files to include before the run begins. + * @property int $reportWidth The maximum number of columns that reports should use for output. + * Set to "auto" for have this value changed to the width of the terminal. + * @property int $errorSeverity The minimum severity an error must have to be displayed. + * @property int $warningSeverity The minimum severity a warning must have to be displayed. + * @property bool $recordErrors Record the content of error messages as well as error counts. + * @property string $suffix A suffix to add to fixed files. + * @property string $basepath A file system location to strip from the paths of files shown in reports. + * @property bool $stdin Read content from STDIN instead of supplied files. + * @property string $stdinContent Content passed directly to PHPCS on STDIN. + * @property string $stdinPath The path to use for content passed on STDIN. + * + * @property array $extensions File extensions that should be checked, and what tokenizer to use. + * E.g., array('inc' => 'PHP'); + * @property array $reports The reports to use for printing output after the run. + * The format of the array is: + * array( + * 'reportName1' => 'outputFile', + * 'reportName2' => null, + * ); + * If the array value is NULL, the report will be written to the screen. + * + * @property string[] $unknown Any arguments gathered on the command line that are unknown to us. + * E.g., using `phpcs -c` will give array('c'); + */ +class Config +{ + + /** + * The current version. + * + * @var string + */ + const VERSION = '3.7.1'; + + /** + * Package stability; either stable, beta or alpha. + * + * @var string + */ + const STABILITY = 'stable'; + + /** + * An array of settings that PHPCS and PHPCBF accept. + * + * This array is not meant to be accessed directly. Instead, use the settings + * as if they are class member vars so the __get() and __set() magic methods + * can be used to validate the values. For example, to set the verbosity level to + * level 2, use $this->verbosity = 2; instead of accessing this property directly. + * + * Each of these settings is described in the class comment property list. + * + * @var array + */ + private $settings = [ + 'files' => null, + 'standards' => null, + 'verbosity' => null, + 'interactive' => null, + 'parallel' => null, + 'cache' => null, + 'cacheFile' => null, + 'colors' => null, + 'explain' => null, + 'local' => null, + 'showSources' => null, + 'showProgress' => null, + 'quiet' => null, + 'annotations' => null, + 'tabWidth' => null, + 'encoding' => null, + 'extensions' => null, + 'sniffs' => null, + 'exclude' => null, + 'ignored' => null, + 'reportFile' => null, + 'generator' => null, + 'filter' => null, + 'bootstrap' => null, + 'reports' => null, + 'basepath' => null, + 'reportWidth' => null, + 'errorSeverity' => null, + 'warningSeverity' => null, + 'recordErrors' => null, + 'suffix' => null, + 'stdin' => null, + 'stdinContent' => null, + 'stdinPath' => null, + 'unknown' => null, + ]; + + /** + * Whether or not to kill the process when an unknown command line arg is found. + * + * If FALSE, arguments that are not command line options or file/directory paths + * will be ignored and execution will continue. These values will be stored in + * $this->unknown. + * + * @var boolean + */ + public $dieOnUnknownArg; + + /** + * The current command line arguments we are processing. + * + * @var string[] + */ + private $cliArgs = []; + + /** + * Command line values that the user has supplied directly. + * + * @var array + */ + private static $overriddenDefaults = []; + + /** + * Config file data that has been loaded for the run. + * + * @var array + */ + private static $configData = null; + + /** + * The full path to the config data file that has been loaded. + * + * @var string + */ + private static $configDataFile = null; + + /** + * Automatically discovered executable utility paths. + * + * @var array + */ + private static $executablePaths = []; + + + /** + * Get the value of an inaccessible property. + * + * @param string $name The name of the property. + * + * @return mixed + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid. + */ + public function __get($name) + { + if (array_key_exists($name, $this->settings) === false) { + throw new RuntimeException("ERROR: unable to get value of property \"$name\""); + } + + return $this->settings[$name]; + + }//end __get() + + + /** + * Set the value of an inaccessible property. + * + * @param string $name The name of the property. + * @param mixed $value The value of the property. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid. + */ + public function __set($name, $value) + { + if (array_key_exists($name, $this->settings) === false) { + throw new RuntimeException("Can't __set() $name; setting doesn't exist"); + } + + switch ($name) { + case 'reportWidth' : + // Support auto terminal width. + if ($value === 'auto' + && function_exists('shell_exec') === true + && preg_match('|\d+ (\d+)|', shell_exec('stty size 2>&1'), $matches) === 1 + ) { + $value = (int) $matches[1]; + } else { + $value = (int) $value; + } + break; + case 'standards' : + $cleaned = []; + + // Check if the standard name is valid, or if the case is invalid. + $installedStandards = Util\Standards::getInstalledStandards(); + foreach ($value as $standard) { + foreach ($installedStandards as $validStandard) { + if (strtolower($standard) === strtolower($validStandard)) { + $standard = $validStandard; + break; + } + } + + $cleaned[] = $standard; + } + + $value = $cleaned; + break; + default : + // No validation required. + break; + }//end switch + + $this->settings[$name] = $value; + + }//end __set() + + + /** + * Check if the value of an inaccessible property is set. + * + * @param string $name The name of the property. + * + * @return bool + */ + public function __isset($name) + { + return isset($this->settings[$name]); + + }//end __isset() + + + /** + * Unset the value of an inaccessible property. + * + * @param string $name The name of the property. + * + * @return void + */ + public function __unset($name) + { + $this->settings[$name] = null; + + }//end __unset() + + + /** + * Get the array of all config settings. + * + * @return array + */ + public function getSettings() + { + return $this->settings; + + }//end getSettings() + + + /** + * Set the array of all config settings. + * + * @param array $settings The array of config settings. + * + * @return void + */ + public function setSettings($settings) + { + return $this->settings = $settings; + + }//end setSettings() + + + /** + * Creates a Config object and populates it with command line values. + * + * @param array $cliArgs An array of values gathered from CLI args. + * @param bool $dieOnUnknownArg Whether or not to kill the process when an + * unknown command line arg is found. + * + * @return void + */ + public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) + { + if (defined('PHP_CODESNIFFER_IN_TESTS') === true) { + // Let everything through during testing so that we can + // make use of PHPUnit command line arguments as well. + $this->dieOnUnknownArg = false; + } else { + $this->dieOnUnknownArg = $dieOnUnknownArg; + } + + if (empty($cliArgs) === true) { + $cliArgs = $_SERVER['argv']; + array_shift($cliArgs); + } + + $this->restoreDefaults(); + $this->setCommandLineValues($cliArgs); + + if (isset(self::$overriddenDefaults['standards']) === false) { + // They did not supply a standard to use. + // Look for a default ruleset in the current directory or higher. + $currentDir = getcwd(); + + $defaultFiles = [ + '.phpcs.xml', + 'phpcs.xml', + '.phpcs.xml.dist', + 'phpcs.xml.dist', + ]; + + do { + foreach ($defaultFiles as $defaultFilename) { + $default = $currentDir.DIRECTORY_SEPARATOR.$defaultFilename; + if (is_file($default) === true) { + $this->standards = [$default]; + break(2); + } + } + + $lastDir = $currentDir; + $currentDir = dirname($currentDir); + } while ($currentDir !== '.' && $currentDir !== $lastDir && Common::isReadable($currentDir) === true); + }//end if + + if (defined('STDIN') === false + || stripos(PHP_OS, 'WIN') === 0 + ) { + return; + } + + $handle = fopen('php://stdin', 'r'); + + // Check for content on STDIN. + if ($this->stdin === true + || (Util\Common::isStdinATTY() === false + && feof($handle) === false) + ) { + $readStreams = [$handle]; + $writeSteams = null; + + $fileContents = ''; + while (is_resource($handle) === true && feof($handle) === false) { + // Set a timeout of 200ms. + if (stream_select($readStreams, $writeSteams, $writeSteams, 0, 200000) === 0) { + break; + } + + $fileContents .= fgets($handle); + } + + if (trim($fileContents) !== '') { + $this->stdin = true; + $this->stdinContent = $fileContents; + self::$overriddenDefaults['stdin'] = true; + self::$overriddenDefaults['stdinContent'] = true; + } + }//end if + + fclose($handle); + + }//end __construct() + + + /** + * Set the command line values. + * + * @param array $args An array of command line arguments to set. + * + * @return void + */ + public function setCommandLineValues($args) + { + $this->cliArgs = $args; + $numArgs = count($args); + + for ($i = 0; $i < $numArgs; $i++) { + $arg = $this->cliArgs[$i]; + if ($arg === '') { + continue; + } + + if ($arg[0] === '-') { + if ($arg === '-') { + // Asking to read from STDIN. + $this->stdin = true; + self::$overriddenDefaults['stdin'] = true; + continue; + } + + if ($arg === '--') { + // Empty argument, ignore it. + continue; + } + + if ($arg[1] === '-') { + $this->processLongArgument(substr($arg, 2), $i); + } else { + $switches = str_split($arg); + foreach ($switches as $switch) { + if ($switch === '-') { + continue; + } + + $this->processShortArgument($switch, $i); + } + } + } else { + $this->processUnknownArgument($arg, $i); + }//end if + }//end for + + }//end setCommandLineValues() + + + /** + * Restore default values for all possible command line arguments. + * + * @return void + */ + public function restoreDefaults() + { + $this->files = []; + $this->standards = ['PEAR']; + $this->verbosity = 0; + $this->interactive = false; + $this->cache = false; + $this->cacheFile = null; + $this->colors = false; + $this->explain = false; + $this->local = false; + $this->showSources = false; + $this->showProgress = false; + $this->quiet = false; + $this->annotations = true; + $this->parallel = 1; + $this->tabWidth = 0; + $this->encoding = 'utf-8'; + $this->extensions = [ + 'php' => 'PHP', + 'inc' => 'PHP', + 'js' => 'JS', + 'css' => 'CSS', + ]; + $this->sniffs = []; + $this->exclude = []; + $this->ignored = []; + $this->reportFile = null; + $this->generator = null; + $this->filter = null; + $this->bootstrap = []; + $this->basepath = null; + $this->reports = ['full' => null]; + $this->reportWidth = 'auto'; + $this->errorSeverity = 5; + $this->warningSeverity = 5; + $this->recordErrors = true; + $this->suffix = ''; + $this->stdin = false; + $this->stdinContent = null; + $this->stdinPath = null; + $this->unknown = []; + + $standard = self::getConfigData('default_standard'); + if ($standard !== null) { + $this->standards = explode(',', $standard); + } + + $reportFormat = self::getConfigData('report_format'); + if ($reportFormat !== null) { + $this->reports = [$reportFormat => null]; + } + + $tabWidth = self::getConfigData('tab_width'); + if ($tabWidth !== null) { + $this->tabWidth = (int) $tabWidth; + } + + $encoding = self::getConfigData('encoding'); + if ($encoding !== null) { + $this->encoding = strtolower($encoding); + } + + $severity = self::getConfigData('severity'); + if ($severity !== null) { + $this->errorSeverity = (int) $severity; + $this->warningSeverity = (int) $severity; + } + + $severity = self::getConfigData('error_severity'); + if ($severity !== null) { + $this->errorSeverity = (int) $severity; + } + + $severity = self::getConfigData('warning_severity'); + if ($severity !== null) { + $this->warningSeverity = (int) $severity; + } + + $showWarnings = self::getConfigData('show_warnings'); + if ($showWarnings !== null) { + $showWarnings = (bool) $showWarnings; + if ($showWarnings === false) { + $this->warningSeverity = 0; + } + } + + $reportWidth = self::getConfigData('report_width'); + if ($reportWidth !== null) { + $this->reportWidth = $reportWidth; + } + + $showProgress = self::getConfigData('show_progress'); + if ($showProgress !== null) { + $this->showProgress = (bool) $showProgress; + } + + $quiet = self::getConfigData('quiet'); + if ($quiet !== null) { + $this->quiet = (bool) $quiet; + } + + $colors = self::getConfigData('colors'); + if ($colors !== null) { + $this->colors = (bool) $colors; + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + $cache = self::getConfigData('cache'); + if ($cache !== null) { + $this->cache = (bool) $cache; + } + + $parallel = self::getConfigData('parallel'); + if ($parallel !== null) { + $this->parallel = max((int) $parallel, 1); + } + } + + }//end restoreDefaults() + + + /** + * Processes a short (-e) command line argument. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processShortArgument($arg, $pos) + { + switch ($arg) { + case 'h': + case '?': + ob_start(); + $this->printUsage(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'i' : + ob_start(); + Util\Standards::printInstalledStandards(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'v' : + if ($this->quiet === true) { + // Ignore when quiet mode is enabled. + break; + } + + $this->verbosity++; + self::$overriddenDefaults['verbosity'] = true; + break; + case 'l' : + $this->local = true; + self::$overriddenDefaults['local'] = true; + break; + case 's' : + $this->showSources = true; + self::$overriddenDefaults['showSources'] = true; + break; + case 'a' : + $this->interactive = true; + self::$overriddenDefaults['interactive'] = true; + break; + case 'e': + $this->explain = true; + self::$overriddenDefaults['explain'] = true; + break; + case 'p' : + if ($this->quiet === true) { + // Ignore when quiet mode is enabled. + break; + } + + $this->showProgress = true; + self::$overriddenDefaults['showProgress'] = true; + break; + case 'q' : + // Quiet mode disables a few other settings as well. + $this->quiet = true; + $this->showProgress = false; + $this->verbosity = 0; + + self::$overriddenDefaults['quiet'] = true; + break; + case 'm' : + $this->recordErrors = false; + self::$overriddenDefaults['recordErrors'] = true; + break; + case 'd' : + $ini = explode('=', $this->cliArgs[($pos + 1)]); + $this->cliArgs[($pos + 1)] = ''; + if (isset($ini[1]) === true) { + ini_set($ini[0], $ini[1]); + } else { + ini_set($ini[0], true); + } + break; + case 'n' : + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + $this->warningSeverity = 0; + self::$overriddenDefaults['warningSeverity'] = true; + } + break; + case 'w' : + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + $this->warningSeverity = $this->errorSeverity; + self::$overriddenDefaults['warningSeverity'] = true; + } + break; + default: + if ($this->dieOnUnknownArg === false) { + $unknown = $this->unknown; + $unknown[] = $arg; + $this->unknown = $unknown; + } else { + $this->processUnknownArgument('-'.$arg, $pos); + } + }//end switch + + }//end processShortArgument() + + + /** + * Processes a long (--example) command line argument. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processLongArgument($arg, $pos) + { + switch ($arg) { + case 'help': + ob_start(); + $this->printUsage(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'version': + $output = 'PHP_CodeSniffer version '.self::VERSION.' ('.self::STABILITY.') '; + $output .= 'by Squiz (http://www.squiz.net)'.PHP_EOL; + throw new DeepExitException($output, 0); + case 'colors': + if (isset(self::$overriddenDefaults['colors']) === true) { + break; + } + + $this->colors = true; + self::$overriddenDefaults['colors'] = true; + break; + case 'no-colors': + if (isset(self::$overriddenDefaults['colors']) === true) { + break; + } + + $this->colors = false; + self::$overriddenDefaults['colors'] = true; + break; + case 'cache': + if (isset(self::$overriddenDefaults['cache']) === true) { + break; + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + $this->cache = true; + self::$overriddenDefaults['cache'] = true; + } + break; + case 'no-cache': + if (isset(self::$overriddenDefaults['cache']) === true) { + break; + } + + $this->cache = false; + self::$overriddenDefaults['cache'] = true; + break; + case 'ignore-annotations': + if (isset(self::$overriddenDefaults['annotations']) === true) { + break; + } + + $this->annotations = false; + self::$overriddenDefaults['annotations'] = true; + break; + case 'config-set': + if (isset($this->cliArgs[($pos + 1)]) === false + || isset($this->cliArgs[($pos + 2)]) === false + ) { + $error = 'ERROR: Setting a config option requires a name and value'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $key = $this->cliArgs[($pos + 1)]; + $value = $this->cliArgs[($pos + 2)]; + $current = self::getConfigData($key); + + try { + $this->setConfigData($key, $value); + } catch (\Exception $e) { + throw new DeepExitException($e->getMessage().PHP_EOL, 3); + } + + $output = 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + + if ($current === null) { + $output .= "Config value \"$key\" added successfully".PHP_EOL; + } else { + $output .= "Config value \"$key\" updated successfully; old value was \"$current\"".PHP_EOL; + } + throw new DeepExitException($output, 0); + case 'config-delete': + if (isset($this->cliArgs[($pos + 1)]) === false) { + $error = 'ERROR: Deleting a config option requires the name of the option'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $output = 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + + $key = $this->cliArgs[($pos + 1)]; + $current = self::getConfigData($key); + if ($current === null) { + $output .= "Config value \"$key\" has not been set".PHP_EOL; + } else { + try { + $this->setConfigData($key, null); + } catch (\Exception $e) { + throw new DeepExitException($e->getMessage().PHP_EOL, 3); + } + + $output .= "Config value \"$key\" removed successfully; old value was \"$current\"".PHP_EOL; + } + throw new DeepExitException($output, 0); + case 'config-show': + ob_start(); + $data = self::getAllConfigData(); + echo 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + $this->printConfigData($data); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'runtime-set': + if (isset($this->cliArgs[($pos + 1)]) === false + || isset($this->cliArgs[($pos + 2)]) === false + ) { + $error = 'ERROR: Setting a runtime config option requires a name and value'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $key = $this->cliArgs[($pos + 1)]; + $value = $this->cliArgs[($pos + 2)]; + $this->cliArgs[($pos + 1)] = ''; + $this->cliArgs[($pos + 2)] = ''; + self::setConfigData($key, $value, true); + if (isset(self::$overriddenDefaults['runtime-set']) === false) { + self::$overriddenDefaults['runtime-set'] = []; + } + + self::$overriddenDefaults['runtime-set'][$key] = true; + break; + default: + if (substr($arg, 0, 7) === 'sniffs=') { + if (isset(self::$overriddenDefaults['sniffs']) === true) { + break; + } + + $sniffs = explode(',', substr($arg, 7)); + foreach ($sniffs as $sniff) { + if (substr_count($sniff, '.') !== 2) { + $error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } + + $this->sniffs = $sniffs; + self::$overriddenDefaults['sniffs'] = true; + } else if (substr($arg, 0, 8) === 'exclude=') { + if (isset(self::$overriddenDefaults['exclude']) === true) { + break; + } + + $sniffs = explode(',', substr($arg, 8)); + foreach ($sniffs as $sniff) { + if (substr_count($sniff, '.') !== 2) { + $error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } + + $this->exclude = $sniffs; + self::$overriddenDefaults['exclude'] = true; + } else if (defined('PHP_CODESNIFFER_IN_TESTS') === false + && substr($arg, 0, 6) === 'cache=' + ) { + if ((isset(self::$overriddenDefaults['cache']) === true + && $this->cache === false) + || isset(self::$overriddenDefaults['cacheFile']) === true + ) { + break; + } + + // Turn caching on. + $this->cache = true; + self::$overriddenDefaults['cache'] = true; + + $this->cacheFile = Util\Common::realpath(substr($arg, 6)); + + // It may not exist and return false instead. + if ($this->cacheFile === false) { + $this->cacheFile = substr($arg, 6); + + $dir = dirname($this->cacheFile); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified cache file path "'.$this->cacheFile.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + if ($dir === '.') { + // Passed cache file is a file in the current directory. + $this->cacheFile = getcwd().'/'.basename($this->cacheFile); + } else { + if ($dir[0] === '/') { + // An absolute path. + $dir = Util\Common::realpath($dir); + } else { + $dir = Util\Common::realpath(getcwd().'/'.$dir); + } + + if ($dir !== false) { + // Cache file path is relative. + $this->cacheFile = $dir.'/'.basename($this->cacheFile); + } + } + }//end if + + self::$overriddenDefaults['cacheFile'] = true; + + if (is_dir($this->cacheFile) === true) { + $error = 'ERROR: The specified cache file path "'.$this->cacheFile.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if (substr($arg, 0, 10) === 'bootstrap=') { + $files = explode(',', substr($arg, 10)); + $bootstrap = []; + foreach ($files as $file) { + $path = Util\Common::realpath($file); + if ($path === false) { + $error = 'ERROR: The specified bootstrap file "'.$file.'" does not exist'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $bootstrap[] = $path; + } + + $this->bootstrap = array_merge($this->bootstrap, $bootstrap); + self::$overriddenDefaults['bootstrap'] = true; + } else if (substr($arg, 0, 10) === 'file-list=') { + $fileList = substr($arg, 10); + $path = Util\Common::realpath($fileList); + if ($path === false) { + $error = 'ERROR: The specified file list "'.$fileList.'" does not exist'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $files = file($path); + foreach ($files as $inputFile) { + $inputFile = trim($inputFile); + + // Skip empty lines. + if ($inputFile === '') { + continue; + } + + $this->processFilePath($inputFile); + } + } else if (substr($arg, 0, 11) === 'stdin-path=') { + if (isset(self::$overriddenDefaults['stdinPath']) === true) { + break; + } + + $this->stdinPath = Util\Common::realpath(substr($arg, 11)); + + // It may not exist and return false instead, so use whatever they gave us. + if ($this->stdinPath === false) { + $this->stdinPath = trim(substr($arg, 11)); + } + + self::$overriddenDefaults['stdinPath'] = true; + } else if (PHP_CODESNIFFER_CBF === false && substr($arg, 0, 12) === 'report-file=') { + if (isset(self::$overriddenDefaults['reportFile']) === true) { + break; + } + + $this->reportFile = Util\Common::realpath(substr($arg, 12)); + + // It may not exist and return false instead. + if ($this->reportFile === false) { + $this->reportFile = substr($arg, 12); + + $dir = Util\Common::realpath(dirname($this->reportFile)); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified report file path "'.$this->reportFile.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $this->reportFile = $dir.'/'.basename($this->reportFile); + }//end if + + self::$overriddenDefaults['reportFile'] = true; + + if (is_dir($this->reportFile) === true) { + $error = 'ERROR: The specified report file path "'.$this->reportFile.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if (substr($arg, 0, 13) === 'report-width=') { + if (isset(self::$overriddenDefaults['reportWidth']) === true) { + break; + } + + $this->reportWidth = substr($arg, 13); + self::$overriddenDefaults['reportWidth'] = true; + } else if (substr($arg, 0, 9) === 'basepath=') { + if (isset(self::$overriddenDefaults['basepath']) === true) { + break; + } + + self::$overriddenDefaults['basepath'] = true; + + if (substr($arg, 9) === '') { + $this->basepath = null; + break; + } + + $this->basepath = Util\Common::realpath(substr($arg, 9)); + + // It may not exist and return false instead. + if ($this->basepath === false) { + $this->basepath = substr($arg, 9); + } + + if (is_dir($this->basepath) === false) { + $error = 'ERROR: The specified basepath "'.$this->basepath.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if ((substr($arg, 0, 7) === 'report=' || substr($arg, 0, 7) === 'report-')) { + $reports = []; + + if ($arg[6] === '-') { + // This is a report with file output. + $split = strpos($arg, '='); + if ($split === false) { + $report = substr($arg, 7); + $output = null; + } else { + $report = substr($arg, 7, ($split - 7)); + $output = substr($arg, ($split + 1)); + if ($output === false) { + $output = null; + } else { + $dir = Util\Common::realpath(dirname($output)); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified '.$report.' report file path "'.$output.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $output = $dir.'/'.basename($output); + + if (is_dir($output) === true) { + $error = 'ERROR: The specified '.$report.' report file path "'.$output.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + }//end if + }//end if + + $reports[$report] = $output; + } else { + // This is a single report. + if (isset(self::$overriddenDefaults['reports']) === true) { + break; + } + + $reportNames = explode(',', substr($arg, 7)); + foreach ($reportNames as $report) { + $reports[$report] = null; + } + }//end if + + // Remove the default value so the CLI value overrides it. + if (isset(self::$overriddenDefaults['reports']) === false) { + $this->reports = $reports; + } else { + $this->reports = array_merge($this->reports, $reports); + } + + self::$overriddenDefaults['reports'] = true; + } else if (substr($arg, 0, 7) === 'filter=') { + if (isset(self::$overriddenDefaults['filter']) === true) { + break; + } + + $this->filter = substr($arg, 7); + self::$overriddenDefaults['filter'] = true; + } else if (substr($arg, 0, 9) === 'standard=') { + $standards = trim(substr($arg, 9)); + if ($standards !== '') { + $this->standards = explode(',', $standards); + } + + self::$overriddenDefaults['standards'] = true; + } else if (substr($arg, 0, 11) === 'extensions=') { + if (isset(self::$overriddenDefaults['extensions']) === true) { + break; + } + + $extensions = explode(',', substr($arg, 11)); + $newExtensions = []; + foreach ($extensions as $ext) { + $slash = strpos($ext, '/'); + if ($slash !== false) { + // They specified the tokenizer too. + list($ext, $tokenizer) = explode('/', $ext); + $newExtensions[$ext] = strtoupper($tokenizer); + continue; + } + + if (isset($this->extensions[$ext]) === true) { + $newExtensions[$ext] = $this->extensions[$ext]; + } else { + $newExtensions[$ext] = 'PHP'; + } + } + + $this->extensions = $newExtensions; + self::$overriddenDefaults['extensions'] = true; + } else if (substr($arg, 0, 7) === 'suffix=') { + if (isset(self::$overriddenDefaults['suffix']) === true) { + break; + } + + $this->suffix = substr($arg, 7); + self::$overriddenDefaults['suffix'] = true; + } else if (substr($arg, 0, 9) === 'parallel=') { + if (isset(self::$overriddenDefaults['parallel']) === true) { + break; + } + + $this->parallel = max((int) substr($arg, 9), 1); + self::$overriddenDefaults['parallel'] = true; + } else if (substr($arg, 0, 9) === 'severity=') { + $this->errorSeverity = (int) substr($arg, 9); + $this->warningSeverity = $this->errorSeverity; + if (isset(self::$overriddenDefaults['errorSeverity']) === false) { + self::$overriddenDefaults['errorSeverity'] = true; + } + + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + self::$overriddenDefaults['warningSeverity'] = true; + } + } else if (substr($arg, 0, 15) === 'error-severity=') { + if (isset(self::$overriddenDefaults['errorSeverity']) === true) { + break; + } + + $this->errorSeverity = (int) substr($arg, 15); + self::$overriddenDefaults['errorSeverity'] = true; + } else if (substr($arg, 0, 17) === 'warning-severity=') { + if (isset(self::$overriddenDefaults['warningSeverity']) === true) { + break; + } + + $this->warningSeverity = (int) substr($arg, 17); + self::$overriddenDefaults['warningSeverity'] = true; + } else if (substr($arg, 0, 7) === 'ignore=') { + if (isset(self::$overriddenDefaults['ignored']) === true) { + break; + } + + // Split the ignore string on commas, unless the comma is escaped + // using 1 or 3 slashes (\, or \\\,). + $patterns = preg_split( + '/(?<=(?ignored = $ignored; + self::$overriddenDefaults['ignored'] = true; + } else if (substr($arg, 0, 10) === 'generator=' + && PHP_CODESNIFFER_CBF === false + ) { + if (isset(self::$overriddenDefaults['generator']) === true) { + break; + } + + $this->generator = substr($arg, 10); + self::$overriddenDefaults['generator'] = true; + } else if (substr($arg, 0, 9) === 'encoding=') { + if (isset(self::$overriddenDefaults['encoding']) === true) { + break; + } + + $this->encoding = strtolower(substr($arg, 9)); + self::$overriddenDefaults['encoding'] = true; + } else if (substr($arg, 0, 10) === 'tab-width=') { + if (isset(self::$overriddenDefaults['tabWidth']) === true) { + break; + } + + $this->tabWidth = (int) substr($arg, 10); + self::$overriddenDefaults['tabWidth'] = true; + } else { + if ($this->dieOnUnknownArg === false) { + $eqPos = strpos($arg, '='); + try { + if ($eqPos === false) { + $this->values[$arg] = $arg; + } else { + $value = substr($arg, ($eqPos + 1)); + $arg = substr($arg, 0, $eqPos); + $this->values[$arg] = $value; + } + } catch (RuntimeException $e) { + // Value is not valid, so just ignore it. + } + } else { + $this->processUnknownArgument('--'.$arg, $pos); + } + }//end if + break; + }//end switch + + }//end processLongArgument() + + + /** + * Processes an unknown command line argument. + * + * Assumes all unknown arguments are files and folders to check. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processUnknownArgument($arg, $pos) + { + // We don't know about any additional switches; just files. + if ($arg[0] === '-') { + if ($this->dieOnUnknownArg === false) { + return; + } + + $error = "ERROR: option \"$arg\" not known".PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $this->processFilePath($arg); + + }//end processUnknownArgument() + + + /** + * Processes a file path and add it to the file list. + * + * @param string $path The path to the file to add. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processFilePath($path) + { + // If we are processing STDIN, don't record any files to check. + if ($this->stdin === true) { + return; + } + + $file = Util\Common::realpath($path); + if (file_exists($file) === false) { + if ($this->dieOnUnknownArg === false) { + return; + } + + $error = 'ERROR: The file "'.$path.'" does not exist.'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } else { + // Can't modify the files array directly because it's not a real + // class member, so need to use this little get/modify/set trick. + $files = $this->files; + $files[] = $file; + $this->files = $files; + self::$overriddenDefaults['files'] = true; + } + + }//end processFilePath() + + + /** + * Prints out the usage information for this script. + * + * @return void + */ + public function printUsage() + { + echo PHP_EOL; + + if (PHP_CODESNIFFER_CBF === true) { + $this->printPHPCBFUsage(); + } else { + $this->printPHPCSUsage(); + } + + echo PHP_EOL; + + }//end printUsage() + + + /** + * Prints out the short usage information for this script. + * + * @param bool $return If TRUE, the usage string is returned + * instead of output to screen. + * + * @return string|void + */ + public function printShortUsage($return=false) + { + if (PHP_CODESNIFFER_CBF === true) { + $usage = 'Run "phpcbf --help" for usage information'; + } else { + $usage = 'Run "phpcs --help" for usage information'; + } + + $usage .= PHP_EOL.PHP_EOL; + + if ($return === true) { + return $usage; + } + + echo $usage; + + }//end printShortUsage() + + + /** + * Prints out the usage information for PHPCS. + * + * @return void + */ + public function printPHPCSUsage() + { + echo 'Usage: phpcs [-nwlsaepqvi] [-d key[=value]] [--colors] [--no-colors]'.PHP_EOL; + echo ' [--cache[=]] [--no-cache] [--tab-width=]'.PHP_EOL; + echo ' [--report=] [--report-file=] [--report-=]'.PHP_EOL; + echo ' [--report-width=] [--basepath=] [--bootstrap=]'.PHP_EOL; + echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; + echo ' [--runtime-set key value] [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL; + echo ' [--standard=] [--sniffs=] [--exclude=]'.PHP_EOL; + echo ' [--encoding=] [--parallel=] [--generator=]'.PHP_EOL; + echo ' [--extensions=] [--ignore=] [--ignore-annotations]'.PHP_EOL; + echo ' [--stdin-path=] [--file-list=] [--filter=] - ...'.PHP_EOL; + echo PHP_EOL; + echo ' - Check STDIN instead of local files and directories'.PHP_EOL; + echo ' -n Do not print warnings (shortcut for --warning-severity=0)'.PHP_EOL; + echo ' -w Print both warnings and errors (this is the default)'.PHP_EOL; + echo ' -l Local directory only, no recursion'.PHP_EOL; + echo ' -s Show sniff codes in all reports'.PHP_EOL; + echo ' -a Run interactively'.PHP_EOL; + echo ' -e Explain a standard by showing the sniffs it includes'.PHP_EOL; + echo ' -p Show progress of the run'.PHP_EOL; + echo ' -q Quiet mode; disables progress and verbose output'.PHP_EOL; + echo ' -m Stop error messages from being recorded'.PHP_EOL; + echo ' (saves a lot of memory, but stops many reports from being used)'.PHP_EOL; + echo ' -v Print processed files'.PHP_EOL; + echo ' -vv Print ruleset and token output'.PHP_EOL; + echo ' -vvv Print sniff processing information'.PHP_EOL; + echo ' -i Show a list of installed coding standards'.PHP_EOL; + echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL; + echo PHP_EOL; + echo ' --help Print this help message'.PHP_EOL; + echo ' --version Print version information'.PHP_EOL; + echo ' --colors Use colors in output'.PHP_EOL; + echo ' --no-colors Do not use colors in output (this is the default)'.PHP_EOL; + echo ' --cache Cache results between runs'.PHP_EOL; + echo ' --no-cache Do not cache results between runs (this is the default)'.PHP_EOL; + echo ' --ignore-annotations Ignore all phpcs: annotations in code comments'.PHP_EOL; + echo PHP_EOL; + echo ' Use a specific file for caching (uses a temporary file by default)'.PHP_EOL; + echo ' A path to strip from the front of file paths inside reports'.PHP_EOL; + echo ' A comma separated list of files to run before processing begins'.PHP_EOL; + echo ' The encoding of the files being checked (default is utf-8)'.PHP_EOL; + echo ' A comma separated list of file extensions to check'.PHP_EOL; + echo ' The type of the file can be specified using: ext/type'.PHP_EOL; + echo ' e.g., module/php,es/js'.PHP_EOL; + echo ' One or more files and/or directories to check'.PHP_EOL; + echo ' A file containing a list of files and/or directories to check (one per line)'.PHP_EOL; + echo ' Use either the "gitmodified" or "gitstaged" filter,'.PHP_EOL; + echo ' or specify the path to a custom filter class'.PHP_EOL; + echo ' Use either the "HTML", "Markdown" or "Text" generator'.PHP_EOL; + echo ' (forces documentation generation instead of checking)'.PHP_EOL; + echo ' A comma separated list of patterns to ignore files and directories'.PHP_EOL; + echo ' How many files should be checked simultaneously (default is 1)'.PHP_EOL; + echo ' Print either the "full", "xml", "checkstyle", "csv"'.PHP_EOL; + echo ' "json", "junit", "emacs", "source", "summary", "diff"'.PHP_EOL; + echo ' "svnblame", "gitblame", "hgblame" or "notifysend" report,'.PHP_EOL; + echo ' or specify the path to a custom report class'.PHP_EOL; + echo ' (the "full" report is printed by default)'.PHP_EOL; + echo ' Write the report to the specified file path'.PHP_EOL; + echo ' How many columns wide screen reports should be printed'.PHP_EOL; + echo ' or set to "auto" to use current screen width, where supported'.PHP_EOL; + echo ' The minimum severity required to display an error or warning'.PHP_EOL; + echo ' A comma separated list of sniff codes to include or exclude from checking'.PHP_EOL; + echo ' (all sniffs must be part of the specified standard)'.PHP_EOL; + echo ' The name or path of the coding standard to use'.PHP_EOL; + echo ' If processing STDIN, the file path that STDIN will be processed as'.PHP_EOL; + echo ' The number of spaces each tab represents'.PHP_EOL; + + }//end printPHPCSUsage() + + + /** + * Prints out the usage information for PHPCBF. + * + * @return void + */ + public function printPHPCBFUsage() + { + echo 'Usage: phpcbf [-nwli] [-d key[=value]] [--ignore-annotations] [--bootstrap=]'.PHP_EOL; + echo ' [--standard=] [--sniffs=] [--exclude=] [--suffix=]'.PHP_EOL; + echo ' [--severity=] [--error-severity=] [--warning-severity=]'.PHP_EOL; + echo ' [--tab-width=] [--encoding=] [--parallel=]'.PHP_EOL; + echo ' [--basepath=] [--extensions=] [--ignore=]'.PHP_EOL; + echo ' [--stdin-path=] [--file-list=] [--filter=] - ...'.PHP_EOL; + echo PHP_EOL; + echo ' - Fix STDIN instead of local files and directories'.PHP_EOL; + echo ' -n Do not fix warnings (shortcut for --warning-severity=0)'.PHP_EOL; + echo ' -w Fix both warnings and errors (on by default)'.PHP_EOL; + echo ' -l Local directory only, no recursion'.PHP_EOL; + echo ' -p Show progress of the run'.PHP_EOL; + echo ' -q Quiet mode; disables progress and verbose output'.PHP_EOL; + echo ' -v Print processed files'.PHP_EOL; + echo ' -vv Print ruleset and token output'.PHP_EOL; + echo ' -vvv Print sniff processing information'.PHP_EOL; + echo ' -i Show a list of installed coding standards'.PHP_EOL; + echo ' -d Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL; + echo PHP_EOL; + echo ' --help Print this help message'.PHP_EOL; + echo ' --version Print version information'.PHP_EOL; + echo ' --ignore-annotations Ignore all phpcs: annotations in code comments'.PHP_EOL; + echo PHP_EOL; + echo ' A path to strip from the front of file paths inside reports'.PHP_EOL; + echo ' A comma separated list of files to run before processing begins'.PHP_EOL; + echo ' The encoding of the files being fixed (default is utf-8)'.PHP_EOL; + echo ' A comma separated list of file extensions to fix'.PHP_EOL; + echo ' The type of the file can be specified using: ext/type'.PHP_EOL; + echo ' e.g., module/php,es/js'.PHP_EOL; + echo ' One or more files and/or directories to fix'.PHP_EOL; + echo ' A file containing a list of files and/or directories to fix (one per line)'.PHP_EOL; + echo ' Use either the "gitmodified" or "gitstaged" filter,'.PHP_EOL; + echo ' or specify the path to a custom filter class'.PHP_EOL; + echo ' A comma separated list of patterns to ignore files and directories'.PHP_EOL; + echo ' How many files should be fixed simultaneously (default is 1)'.PHP_EOL; + echo ' The minimum severity required to fix an error or warning'.PHP_EOL; + echo ' A comma separated list of sniff codes to include or exclude from fixing'.PHP_EOL; + echo ' (all sniffs must be part of the specified standard)'.PHP_EOL; + echo ' The name or path of the coding standard to use'.PHP_EOL; + echo ' If processing STDIN, the file path that STDIN will be processed as'.PHP_EOL; + echo ' Write modified files to a filename using this suffix'.PHP_EOL; + echo ' ("diff" and "patch" are not used in this mode)'.PHP_EOL; + echo ' The number of spaces each tab represents'.PHP_EOL; + + }//end printPHPCBFUsage() + + + /** + * Get a single config value. + * + * @param string $key The name of the config value. + * + * @return string|null + * @see setConfigData() + * @see getAllConfigData() + */ + public static function getConfigData($key) + { + $phpCodeSnifferConfig = self::getAllConfigData(); + + if ($phpCodeSnifferConfig === null) { + return null; + } + + if (isset($phpCodeSnifferConfig[$key]) === false) { + return null; + } + + return $phpCodeSnifferConfig[$key]; + + }//end getConfigData() + + + /** + * Get the path to an executable utility. + * + * @param string $name The name of the executable utility. + * + * @return string|null + * @see getConfigData() + */ + public static function getExecutablePath($name) + { + $data = self::getConfigData($name.'_path'); + if ($data !== null) { + return $data; + } + + if ($name === "php") { + // For php, we know the executable path. There's no need to look it up. + return PHP_BINARY; + } + + if (array_key_exists($name, self::$executablePaths) === true) { + return self::$executablePaths[$name]; + } + + if (stripos(PHP_OS, 'WIN') === 0) { + $cmd = 'where '.escapeshellarg($name).' 2> nul'; + } else { + $cmd = 'which '.escapeshellarg($name).' 2> /dev/null'; + } + + $result = exec($cmd, $output, $retVal); + if ($retVal !== 0) { + $result = null; + } + + self::$executablePaths[$name] = $result; + return $result; + + }//end getExecutablePath() + + + /** + * Set a single config value. + * + * @param string $key The name of the config value. + * @param string|null $value The value to set. If null, the config + * entry is deleted, reverting it to the + * default value. + * @param boolean $temp Set this config data temporarily for this + * script run. This will not write the config + * data to the config file. + * + * @return bool + * @see getConfigData() + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file can not be written. + */ + public static function setConfigData($key, $value, $temp=false) + { + if (isset(self::$overriddenDefaults['runtime-set']) === true + && isset(self::$overriddenDefaults['runtime-set'][$key]) === true + ) { + return false; + } + + if ($temp === false) { + $path = ''; + if (is_callable('\Phar::running') === true) { + $path = \Phar::running(false); + } + + if ($path !== '') { + $configFile = dirname($path).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } else { + $configFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + if (is_file($configFile) === false + && strpos('@data_dir@', '@data_dir') === false + ) { + // If data_dir was replaced, this is a PEAR install and we can + // use the PEAR data dir to store the conf file. + $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf'; + } + } + + if (is_file($configFile) === true + && is_writable($configFile) === false + ) { + $error = 'ERROR: Config file '.$configFile.' is not writable'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + }//end if + + $phpCodeSnifferConfig = self::getAllConfigData(); + + if ($value === null) { + if (isset($phpCodeSnifferConfig[$key]) === true) { + unset($phpCodeSnifferConfig[$key]); + } + } else { + $phpCodeSnifferConfig[$key] = $value; + } + + if ($temp === false) { + $output = '<'.'?php'."\n".' $phpCodeSnifferConfig = '; + $output .= var_export($phpCodeSnifferConfig, true); + $output .= ";\n?".'>'; + + if (file_put_contents($configFile, $output) === false) { + $error = 'ERROR: Config file '.$configFile.' could not be written'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + self::$configDataFile = $configFile; + } + + self::$configData = $phpCodeSnifferConfig; + + // If the installed paths are being set, make sure all known + // standards paths are added to the autoloader. + if ($key === 'installed_paths') { + $installedStandards = Util\Standards::getInstalledStandardDetails(); + foreach ($installedStandards as $name => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + } + } + + return true; + + }//end setConfigData() + + + /** + * Get all config data. + * + * @return array + * @see getConfigData() + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file could not be read. + */ + public static function getAllConfigData() + { + if (self::$configData !== null) { + return self::$configData; + } + + $path = ''; + if (is_callable('\Phar::running') === true) { + $path = \Phar::running(false); + } + + if ($path !== '') { + $configFile = dirname($path).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } else { + $configFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + if (is_file($configFile) === false + && strpos('@data_dir@', '@data_dir') === false + ) { + $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf'; + } + } + + if (is_file($configFile) === false) { + self::$configData = []; + return []; + } + + if (Common::isReadable($configFile) === false) { + $error = 'ERROR: Config file '.$configFile.' is not readable'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + include $configFile; + self::$configDataFile = $configFile; + self::$configData = $phpCodeSnifferConfig; + return self::$configData; + + }//end getAllConfigData() + + + /** + * Prints out the gathered config data. + * + * @param array $data The config data to print. + * + * @return void + */ + public function printConfigData($data) + { + $max = 0; + $keys = array_keys($data); + foreach ($keys as $key) { + $len = strlen($key); + if (strlen($key) > $max) { + $max = $len; + } + } + + if ($max === 0) { + return; + } + + $max += 2; + ksort($data); + foreach ($data as $name => $value) { + echo str_pad($name.': ', $max).$value.PHP_EOL; + } + + }//end printConfigData() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php b/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php new file mode 100644 index 000000000..b1440944a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php @@ -0,0 +1,18 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +class DeepExitException extends \Exception +{ + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php b/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php new file mode 100644 index 000000000..093bf13d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php @@ -0,0 +1,15 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +class RuntimeException extends \RuntimeException +{ + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php b/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php new file mode 100644 index 000000000..ceba00ccd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php @@ -0,0 +1,15 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +class TokenizerException extends \Exception +{ + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Files/DummyFile.php b/kirki-composer/squizlabs/php_codesniffer/src/Files/DummyFile.php new file mode 100644 index 000000000..601430301 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Files/DummyFile.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; + +class DummyFile extends File +{ + + + /** + * Creates a DummyFile object and sets the content. + * + * @param string $content The content of the file. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($content, Ruleset $ruleset, Config $config) + { + $this->setContent($content); + + // See if a filename was defined in the content. + // This is done by including: phpcs_input_file: [file path] + // as the first line of content. + $path = 'STDIN'; + if ($content !== '') { + if (substr($content, 0, 17) === 'phpcs_input_file:') { + $eolPos = strpos($content, $this->eolChar); + $filename = trim(substr($content, 17, ($eolPos - 17))); + $content = substr($content, ($eolPos + strlen($this->eolChar))); + $path = $filename; + + $this->setContent($content); + } + } + + // The CLI arg overrides anything passed in the content. + if ($config->stdinPath !== null) { + $path = $config->stdinPath; + } + + parent::__construct($path, $ruleset, $config); + + }//end __construct() + + + /** + * Set the error, warning, and fixable counts for the file. + * + * @param int $errorCount The number of errors found. + * @param int $warningCount The number of warnings found. + * @param int $fixableCount The number of fixable errors found. + * @param int $fixedCount The number of errors that were fixed. + * + * @return void + */ + public function setErrorCounts($errorCount, $warningCount, $fixableCount, $fixedCount) + { + $this->errorCount = $errorCount; + $this->warningCount = $warningCount; + $this->fixableCount = $fixableCount; + $this->fixedCount = $fixedCount; + + }//end setErrorCounts() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Files/File.php b/kirki-composer/squizlabs/php_codesniffer/src/Files/File.php new file mode 100644 index 000000000..a15af762f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Files/File.php @@ -0,0 +1,2829 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Fixer; +use PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Exceptions\TokenizerException; + +class File +{ + + /** + * The absolute path to the file associated with this object. + * + * @var string + */ + public $path = ''; + + /** + * The content of the file. + * + * @var string + */ + protected $content = ''; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * If TRUE, the entire file is being ignored. + * + * @var boolean + */ + public $ignored = false; + + /** + * The EOL character this file uses. + * + * @var string + */ + public $eolChar = ''; + + /** + * The Fixer object to control fixing errors. + * + * @var \PHP_CodeSniffer\Fixer + */ + public $fixer = null; + + /** + * The tokenizer being used for this file. + * + * @var \PHP_CodeSniffer\Tokenizers\Tokenizer + */ + public $tokenizer = null; + + /** + * The name of the tokenizer being used for this file. + * + * @var string + */ + public $tokenizerType = 'PHP'; + + /** + * Was the file loaded from cache? + * + * If TRUE, the file was loaded from a local cache. + * If FALSE, the file was tokenized and processed fully. + * + * @var boolean + */ + public $fromCache = false; + + /** + * The number of tokens in this file. + * + * Stored here to save calling count() everywhere. + * + * @var integer + */ + public $numTokens = 0; + + /** + * The tokens stack map. + * + * @var array + */ + protected $tokens = []; + + /** + * The errors raised from sniffs. + * + * @var array + * @see getErrors() + */ + protected $errors = []; + + /** + * The warnings raised from sniffs. + * + * @var array + * @see getWarnings() + */ + protected $warnings = []; + + /** + * The metrics recorded by sniffs. + * + * @var array + * @see getMetrics() + */ + protected $metrics = []; + + /** + * The metrics recorded for each token. + * + * Stops the same metric being recorded for the same token twice. + * + * @var array + * @see getMetrics() + */ + private $metricTokens = []; + + /** + * The total number of errors raised. + * + * @var integer + */ + protected $errorCount = 0; + + /** + * The total number of warnings raised. + * + * @var integer + */ + protected $warningCount = 0; + + /** + * The total number of errors and warnings that can be fixed. + * + * @var integer + */ + protected $fixableCount = 0; + + /** + * The total number of errors and warnings that were fixed. + * + * @var integer + */ + protected $fixedCount = 0; + + /** + * TRUE if errors are being replayed from the cache. + * + * @var boolean + */ + protected $replayingErrors = false; + + /** + * An array of sniffs that are being ignored. + * + * @var array + */ + protected $ignoredListeners = []; + + /** + * An array of message codes that are being ignored. + * + * @var array + */ + protected $ignoredCodes = []; + + /** + * An array of sniffs listening to this file's processing. + * + * @var \PHP_CodeSniffer\Sniffs\Sniff[] + */ + protected $listeners = []; + + /** + * The class name of the sniff currently processing the file. + * + * @var string + */ + protected $activeListener = ''; + + /** + * An array of sniffs being processed and how long they took. + * + * @var array + */ + protected $listenerTimes = []; + + /** + * A cache of often used config settings to improve performance. + * + * Storing them here saves 10k+ calls to __get() in the Config class. + * + * @var array + */ + protected $configCache = []; + + + /** + * Constructs a file. + * + * @param string $path The absolute path to the file to process. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($path, Ruleset $ruleset, Config $config) + { + $this->path = $path; + $this->ruleset = $ruleset; + $this->config = $config; + $this->fixer = new Fixer(); + + $parts = explode('.', $path); + $extension = array_pop($parts); + if (isset($config->extensions[$extension]) === true) { + $this->tokenizerType = $config->extensions[$extension]; + } else { + // Revert to default. + $this->tokenizerType = 'PHP'; + } + + $this->configCache['cache'] = $this->config->cache; + $this->configCache['sniffs'] = array_map('strtolower', $this->config->sniffs); + $this->configCache['exclude'] = array_map('strtolower', $this->config->exclude); + $this->configCache['errorSeverity'] = $this->config->errorSeverity; + $this->configCache['warningSeverity'] = $this->config->warningSeverity; + $this->configCache['recordErrors'] = $this->config->recordErrors; + $this->configCache['ignorePatterns'] = $this->ruleset->ignorePatterns; + $this->configCache['includePatterns'] = $this->ruleset->includePatterns; + + }//end __construct() + + + /** + * Set the content of the file. + * + * Setting the content also calculates the EOL char being used. + * + * @param string $content The file content. + * + * @return void + */ + public function setContent($content) + { + $this->content = $content; + $this->tokens = []; + + try { + $this->eolChar = Util\Common::detectLineEndings($content); + } catch (RuntimeException $e) { + $this->addWarningOnLine($e->getMessage(), 1, 'Internal.DetectLineEndings'); + return; + } + + }//end setContent() + + + /** + * Reloads the content of the file. + * + * By default, we have no idea where our content comes from, + * so we can't do anything. + * + * @return void + */ + public function reloadContent() + { + + }//end reloadContent() + + + /** + * Disables caching of this file. + * + * @return void + */ + public function disableCaching() + { + $this->configCache['cache'] = false; + + }//end disableCaching() + + + /** + * Starts the stack traversal and tells listeners when tokens are found. + * + * @return void + */ + public function process() + { + if ($this->ignored === true) { + return; + } + + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + + $this->parse(); + + // Check if tokenizer errors cause this file to be ignored. + if ($this->ignored === true) { + return; + } + + $this->fixer->startFile($this); + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t*** START TOKEN PROCESSING ***".PHP_EOL; + } + + $foundCode = false; + $listenerIgnoreTo = []; + $inTests = defined('PHP_CODESNIFFER_IN_TESTS'); + $checkAnnotations = $this->config->annotations; + + // Foreach of the listeners that have registered to listen for this + // token, get them to process it. + foreach ($this->tokens as $stackPtr => $token) { + // Check for ignored lines. + if ($checkAnnotations === true + && ($token['code'] === T_COMMENT + || $token['code'] === T_PHPCS_IGNORE_FILE + || $token['code'] === T_PHPCS_SET + || $token['code'] === T_DOC_COMMENT_STRING + || $token['code'] === T_DOC_COMMENT_TAG + || ($inTests === true && $token['code'] === T_INLINE_HTML)) + ) { + $commentText = ltrim($this->tokens[$stackPtr]['content'], " \t/*#"); + $commentTextLower = strtolower($commentText); + if (strpos($commentText, '@codingStandards') !== false) { + if (strpos($commentText, '@codingStandardsIgnoreFile') !== false) { + // Ignoring the whole file, just a little late. + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + return; + } else if (strpos($commentText, '@codingStandardsChangeSetting') !== false) { + $start = strpos($commentText, '@codingStandardsChangeSetting'); + $comment = substr($commentText, ($start + 30)); + $parts = explode(' ', $comment); + if (count($parts) >= 2) { + $sniffParts = explode('.', $parts[0]); + if (count($sniffParts) >= 3) { + // If the sniff code is not known to us, it has not been registered in this run. + // But don't throw an error as it could be there for a different standard to use. + if (isset($this->ruleset->sniffCodes[$parts[0]]) === true) { + $listenerCode = array_shift($parts); + $propertyCode = array_shift($parts); + $propertyValue = rtrim(implode(' ', $parts), " */\r\n"); + $listenerClass = $this->ruleset->sniffCodes[$listenerCode]; + $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $propertyValue); + } + } + } + }//end if + } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile' + || substr($commentTextLower, 0, 17) === '@phpcs:ignorefile' + ) { + // Ignoring the whole file, just a little late. + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + return; + } else if (substr($commentTextLower, 0, 9) === 'phpcs:set' + || substr($commentTextLower, 0, 10) === '@phpcs:set' + ) { + if (isset($token['sniffCode']) === true) { + $listenerCode = $token['sniffCode']; + if (isset($this->ruleset->sniffCodes[$listenerCode]) === true) { + $propertyCode = $token['sniffProperty']; + $propertyValue = $token['sniffPropertyValue']; + $listenerClass = $this->ruleset->sniffCodes[$listenerCode]; + $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $propertyValue); + } + } + }//end if + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\t\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + if ($token['code'] !== T_INLINE_HTML) { + $foundCode = true; + } + + if (isset($this->ruleset->tokenListeners[$token['code']]) === false) { + continue; + } + + foreach ($this->ruleset->tokenListeners[$token['code']] as $listenerData) { + if (isset($this->ignoredListeners[$listenerData['class']]) === true + || (isset($listenerIgnoreTo[$listenerData['class']]) === true + && $listenerIgnoreTo[$listenerData['class']] > $stackPtr) + ) { + // This sniff is ignoring past this token, or the whole file. + continue; + } + + // Make sure this sniff supports the tokenizer + // we are currently using. + $class = $listenerData['class']; + + if (isset($listenerData['tokenizers'][$this->tokenizerType]) === false) { + continue; + } + + if (trim($this->path, '\'"') !== 'STDIN') { + // If the file path matches one of our ignore patterns, skip it. + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + foreach ($listenerData['ignore'] as $pattern) { + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $pattern = str_replace('/', '\\\\', $pattern); + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $this->path) === 1) { + $this->ignoredListeners[$class] = true; + continue(2); + } + } + + // If the file path does not match one of our include patterns, skip it. + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + if (empty($listenerData['include']) === false) { + $included = false; + foreach ($listenerData['include'] as $pattern) { + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $pattern = str_replace('/', '\\\\', $pattern); + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $this->path) === 1) { + $included = true; + break; + } + } + + if ($included === false) { + $this->ignoredListeners[$class] = true; + continue; + } + }//end if + }//end if + + $this->activeListener = $class; + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $startTime = microtime(true); + echo "\t\t\tProcessing ".$this->activeListener.'... '; + } + + $ignoreTo = $this->ruleset->sniffs[$class]->process($this, $stackPtr); + if ($ignoreTo !== null) { + $listenerIgnoreTo[$this->activeListener] = $ignoreTo; + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $timeTaken = (microtime(true) - $startTime); + if (isset($this->listenerTimes[$this->activeListener]) === false) { + $this->listenerTimes[$this->activeListener] = 0; + } + + $this->listenerTimes[$this->activeListener] += $timeTaken; + + $timeTaken = round(($timeTaken), 4); + echo "DONE in $timeTaken seconds".PHP_EOL; + } + + $this->activeListener = ''; + }//end foreach + }//end foreach + + // If short open tags are off but the file being checked uses + // short open tags, the whole content will be inline HTML + // and nothing will be checked. So try and handle this case. + // We don't show this error for STDIN because we can't be sure the content + // actually came directly from the user. It could be something like + // refs from a Git pre-push hook. + if ($foundCode === false && $this->tokenizerType === 'PHP' && $this->path !== 'STDIN') { + $shortTags = (bool) ini_get('short_open_tag'); + if ($shortTags === false) { + $error = 'No PHP code was found in this file and short open tags are not allowed by this install of PHP. This file may be using short open tags but PHP does not allow them.'; + $this->addWarning($error, null, 'Internal.NoCodeFound'); + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t*** END TOKEN PROCESSING ***".PHP_EOL; + echo "\t*** START SNIFF PROCESSING REPORT ***".PHP_EOL; + + asort($this->listenerTimes, SORT_NUMERIC); + $this->listenerTimes = array_reverse($this->listenerTimes, true); + foreach ($this->listenerTimes as $listener => $timeTaken) { + echo "\t$listener: ".round(($timeTaken), 4).' secs'.PHP_EOL; + } + + echo "\t*** END SNIFF PROCESSING REPORT ***".PHP_EOL; + } + + $this->fixedCount += $this->fixer->getFixCount(); + + }//end process() + + + /** + * Tokenizes the file and prepares it for the test run. + * + * @return void + */ + public function parse() + { + if (empty($this->tokens) === false) { + // File has already been parsed. + return; + } + + try { + $tokenizerClass = 'PHP_CodeSniffer\Tokenizers\\'.$this->tokenizerType; + $this->tokenizer = new $tokenizerClass($this->content, $this->config, $this->eolChar); + $this->tokens = $this->tokenizer->getTokens(); + } catch (TokenizerException $e) { + $this->ignored = true; + $this->addWarning($e->getMessage(), null, 'Internal.Tokenizer.Exception'); + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo "[$this->tokenizerType => tokenizer error]... "; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + return; + } + + $this->numTokens = count($this->tokens); + + // Check for mixed line endings as these can cause tokenizer errors and we + // should let the user know that the results they get may be incorrect. + // This is done by removing all backslashes, removing the newline char we + // detected, then converting newlines chars into text. If any backslashes + // are left at the end, we have additional newline chars in use. + $contents = str_replace('\\', '', $this->content); + $contents = str_replace($this->eolChar, '', $contents); + $contents = str_replace("\n", '\n', $contents); + $contents = str_replace("\r", '\r', $contents); + if (strpos($contents, '\\') !== false) { + $error = 'File has mixed line endings; this may cause incorrect results'; + $this->addWarningOnLine($error, 1, 'Internal.LineEndings.Mixed'); + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($this->numTokens === 0) { + $numLines = 0; + } else { + $numLines = $this->tokens[($this->numTokens - 1)]['line']; + } + + echo "[$this->tokenizerType => $this->numTokens tokens in $numLines lines]... "; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + }//end parse() + + + /** + * Returns the token stack for this file. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + + }//end getTokens() + + + /** + * Remove vars stored in this file that are no longer required. + * + * @return void + */ + public function cleanUp() + { + $this->listenerTimes = null; + $this->content = null; + $this->tokens = null; + $this->metricTokens = null; + $this->tokenizer = null; + $this->fixer = null; + $this->config = null; + $this->ruleset = null; + + }//end cleanUp() + + + /** + * Records an error against a specific token in the file. + * + * @param string $error The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the error be fixed by the sniff? + * + * @return boolean + */ + public function addError( + $error, + $stackPtr, + $code, + $data=[], + $severity=0, + $fixable=false + ) { + if ($stackPtr === null) { + $line = 1; + $column = 1; + } else { + $line = $this->tokens[$stackPtr]['line']; + $column = $this->tokens[$stackPtr]['column']; + } + + return $this->addMessage(true, $error, $line, $column, $code, $data, $severity, $fixable); + + }//end addError() + + + /** + * Records a warning against a specific token in the file. + * + * @param string $warning The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the warning be fixed by the sniff? + * + * @return boolean + */ + public function addWarning( + $warning, + $stackPtr, + $code, + $data=[], + $severity=0, + $fixable=false + ) { + if ($stackPtr === null) { + $line = 1; + $column = 1; + } else { + $line = $this->tokens[$stackPtr]['line']; + $column = $this->tokens[$stackPtr]['column']; + } + + return $this->addMessage(false, $warning, $line, $column, $code, $data, $severity, $fixable); + + }//end addWarning() + + + /** + * Records an error against a specific line in the file. + * + * @param string $error The error message. + * @param int $line The line on which the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addErrorOnLine( + $error, + $line, + $code, + $data=[], + $severity=0 + ) { + return $this->addMessage(true, $error, $line, 1, $code, $data, $severity, false); + + }//end addErrorOnLine() + + + /** + * Records a warning against a specific token in the file. + * + * @param string $warning The error message. + * @param int $line The line on which the warning occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 will + * will be converted into the default severity level. + * + * @return boolean + */ + public function addWarningOnLine( + $warning, + $line, + $code, + $data=[], + $severity=0 + ) { + return $this->addMessage(false, $warning, $line, 1, $code, $data, $severity, false); + + }//end addWarningOnLine() + + + /** + * Records a fixable error against a specific token in the file. + * + * Returns true if the error was recorded and should be fixed. + * + * @param string $error The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addFixableError( + $error, + $stackPtr, + $code, + $data=[], + $severity=0 + ) { + $recorded = $this->addError($error, $stackPtr, $code, $data, $severity, true); + if ($recorded === true && $this->fixer->enabled === true) { + return true; + } + + return false; + + }//end addFixableError() + + + /** + * Records a fixable warning against a specific token in the file. + * + * Returns true if the warning was recorded and should be fixed. + * + * @param string $warning The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addFixableWarning( + $warning, + $stackPtr, + $code, + $data=[], + $severity=0 + ) { + $recorded = $this->addWarning($warning, $stackPtr, $code, $data, $severity, true); + if ($recorded === true && $this->fixer->enabled === true) { + return true; + } + + return false; + + }//end addFixableWarning() + + + /** + * Adds an error to the error stack. + * + * @param boolean $error Is this an error message? + * @param string $message The text of the message. + * @param int $line The line on which the message occurred. + * @param int $column The column at which the message occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the message. + * @param int $severity The severity level for this message. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the problem be fixed by the sniff? + * + * @return boolean + */ + protected function addMessage($error, $message, $line, $column, $code, $data, $severity, $fixable) + { + // Check if this line is ignoring all message codes. + if (isset($this->tokenizer->ignoredLines[$line]['.all']) === true) { + return false; + } + + // Work out which sniff generated the message. + $parts = explode('.', $code); + if ($parts[0] === 'Internal') { + // An internal message. + $listenerCode = Util\Common::getSniffCode($this->activeListener); + $sniffCode = $code; + $checkCodes = [$sniffCode]; + } else { + if ($parts[0] !== $code) { + // The full message code has been passed in. + $sniffCode = $code; + $listenerCode = substr($sniffCode, 0, strrpos($sniffCode, '.')); + } else { + $listenerCode = Util\Common::getSniffCode($this->activeListener); + $sniffCode = $listenerCode.'.'.$code; + $parts = explode('.', $sniffCode); + } + + $checkCodes = [ + $sniffCode, + $parts[0].'.'.$parts[1].'.'.$parts[2], + $parts[0].'.'.$parts[1], + $parts[0], + ]; + }//end if + + if (isset($this->tokenizer->ignoredLines[$line]) === true) { + // Check if this line is ignoring this specific message. + $ignored = false; + foreach ($checkCodes as $checkCode) { + if (isset($this->tokenizer->ignoredLines[$line][$checkCode]) === true) { + $ignored = true; + break; + } + } + + // If it is ignored, make sure it's not whitelisted. + if ($ignored === true + && isset($this->tokenizer->ignoredLines[$line]['.except']) === true + ) { + foreach ($checkCodes as $checkCode) { + if (isset($this->tokenizer->ignoredLines[$line]['.except'][$checkCode]) === true) { + $ignored = false; + break; + } + } + } + + if ($ignored === true) { + return false; + } + }//end if + + $includeAll = true; + if ($this->configCache['cache'] === false + || $this->configCache['recordErrors'] === false + ) { + $includeAll = false; + } + + // Filter out any messages for sniffs that shouldn't have run + // due to the use of the --sniffs command line argument. + if ($includeAll === false + && ((empty($this->configCache['sniffs']) === false + && in_array(strtolower($listenerCode), $this->configCache['sniffs'], true) === false) + || (empty($this->configCache['exclude']) === false + && in_array(strtolower($listenerCode), $this->configCache['exclude'], true) === true)) + ) { + return false; + } + + // If we know this sniff code is being ignored for this file, return early. + foreach ($checkCodes as $checkCode) { + if (isset($this->ignoredCodes[$checkCode]) === true) { + return false; + } + } + + $oppositeType = 'warning'; + if ($error === false) { + $oppositeType = 'error'; + } + + foreach ($checkCodes as $checkCode) { + // Make sure this message type has not been set to the opposite message type. + if (isset($this->ruleset->ruleset[$checkCode]['type']) === true + && $this->ruleset->ruleset[$checkCode]['type'] === $oppositeType + ) { + $error = !$error; + break; + } + } + + if ($error === true) { + $configSeverity = $this->configCache['errorSeverity']; + $messageCount = &$this->errorCount; + $messages = &$this->errors; + } else { + $configSeverity = $this->configCache['warningSeverity']; + $messageCount = &$this->warningCount; + $messages = &$this->warnings; + } + + if ($includeAll === false && $configSeverity === 0) { + // Don't bother doing any processing as these messages are just going to + // be hidden in the reports anyway. + return false; + } + + if ($severity === 0) { + $severity = 5; + } + + foreach ($checkCodes as $checkCode) { + // Make sure we are interested in this severity level. + if (isset($this->ruleset->ruleset[$checkCode]['severity']) === true) { + $severity = $this->ruleset->ruleset[$checkCode]['severity']; + break; + } + } + + if ($includeAll === false && $configSeverity > $severity) { + return false; + } + + // Make sure we are not ignoring this file. + $included = null; + if (trim($this->path, '\'"') === 'STDIN') { + $included = true; + } else { + foreach ($checkCodes as $checkCode) { + $patterns = null; + + if (isset($this->configCache['includePatterns'][$checkCode]) === true) { + $patterns = $this->configCache['includePatterns'][$checkCode]; + $excluding = false; + } else if (isset($this->configCache['ignorePatterns'][$checkCode]) === true) { + $patterns = $this->configCache['ignorePatterns'][$checkCode]; + $excluding = true; + } + + if ($patterns === null) { + continue; + } + + foreach ($patterns as $pattern => $type) { + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $replacements['/'] = '\\\\'; + } + + $pattern = '`'.strtr($pattern, $replacements).'`i'; + $matched = preg_match($pattern, $this->path); + + if ($matched === 0) { + if ($excluding === false && $included === null) { + // This file path is not being included. + $included = false; + } + + continue; + } + + if ($excluding === true) { + // This file path is being excluded. + $this->ignoredCodes[$checkCode] = true; + return false; + } + + // This file path is being included. + $included = true; + break; + }//end foreach + }//end foreach + }//end if + + if ($included === false) { + // There were include rules set, but this file + // path didn't match any of them. + return false; + } + + $messageCount++; + if ($fixable === true) { + $this->fixableCount++; + } + + if ($this->configCache['recordErrors'] === false + && $includeAll === false + ) { + return true; + } + + // See if there is a custom error message format to use. + // But don't do this if we are replaying errors because replayed + // errors have already used the custom format and have had their + // data replaced. + if ($this->replayingErrors === false + && isset($this->ruleset->ruleset[$sniffCode]['message']) === true + ) { + $message = $this->ruleset->ruleset[$sniffCode]['message']; + } + + if (empty($data) === false) { + $message = vsprintf($message, $data); + } + + if (isset($messages[$line]) === false) { + $messages[$line] = []; + } + + if (isset($messages[$line][$column]) === false) { + $messages[$line][$column] = []; + } + + $messages[$line][$column][] = [ + 'message' => $message, + 'source' => $sniffCode, + 'listener' => $this->activeListener, + 'severity' => $severity, + 'fixable' => $fixable, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1 + && $this->fixer->enabled === true + && $fixable === true + ) { + @ob_end_clean(); + echo "\tE: [Line $line] $message ($sniffCode)".PHP_EOL; + ob_start(); + } + + return true; + + }//end addMessage() + + + /** + * Record a metric about the file being examined. + * + * @param int $stackPtr The stack position where the metric was recorded. + * @param string $metric The name of the metric being recorded. + * @param string $value The value of the metric being recorded. + * + * @return boolean + */ + public function recordMetric($stackPtr, $metric, $value) + { + if (isset($this->metrics[$metric]) === false) { + $this->metrics[$metric] = ['values' => [$value => 1]]; + $this->metricTokens[$metric][$stackPtr] = true; + } else if (isset($this->metricTokens[$metric][$stackPtr]) === false) { + $this->metricTokens[$metric][$stackPtr] = true; + if (isset($this->metrics[$metric]['values'][$value]) === false) { + $this->metrics[$metric]['values'][$value] = 1; + } else { + $this->metrics[$metric]['values'][$value]++; + } + } + + return true; + + }//end recordMetric() + + + /** + * Returns the number of errors raised. + * + * @return int + */ + public function getErrorCount() + { + return $this->errorCount; + + }//end getErrorCount() + + + /** + * Returns the number of warnings raised. + * + * @return int + */ + public function getWarningCount() + { + return $this->warningCount; + + }//end getWarningCount() + + + /** + * Returns the number of fixable errors/warnings raised. + * + * @return int + */ + public function getFixableCount() + { + return $this->fixableCount; + + }//end getFixableCount() + + + /** + * Returns the number of fixed errors/warnings. + * + * @return int + */ + public function getFixedCount() + { + return $this->fixedCount; + + }//end getFixedCount() + + + /** + * Returns the list of ignored lines. + * + * @return array + */ + public function getIgnoredLines() + { + return $this->tokenizer->ignoredLines; + + }//end getIgnoredLines() + + + /** + * Returns the errors raised from processing this file. + * + * @return array + */ + public function getErrors() + { + return $this->errors; + + }//end getErrors() + + + /** + * Returns the warnings raised from processing this file. + * + * @return array + */ + public function getWarnings() + { + return $this->warnings; + + }//end getWarnings() + + + /** + * Returns the metrics found while processing this file. + * + * @return array + */ + public function getMetrics() + { + return $this->metrics; + + }//end getMetrics() + + + /** + * Returns the absolute filename of this file. + * + * @return string + */ + public function getFilename() + { + return $this->path; + + }//end getFilename() + + + /** + * Returns the declaration name for classes, interfaces, traits, enums, and functions. + * + * @param int $stackPtr The position of the declaration token which + * declared the class, interface, trait, or function. + * + * @return string|null The name of the class, interface, trait, or function; + * or NULL if the function or class is anonymous. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified token is not of type + * T_FUNCTION, T_CLASS, T_ANON_CLASS, + * T_CLOSURE, T_TRAIT, T_ENUM, or T_INTERFACE. + */ + public function getDeclarationName($stackPtr) + { + $tokenCode = $this->tokens[$stackPtr]['code']; + + if ($tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + return null; + } + + if ($tokenCode !== T_FUNCTION + && $tokenCode !== T_CLASS + && $tokenCode !== T_INTERFACE + && $tokenCode !== T_TRAIT + && $tokenCode !== T_ENUM + ) { + throw new RuntimeException('Token type "'.$this->tokens[$stackPtr]['type'].'" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM'); + } + + if ($tokenCode === T_FUNCTION + && strtolower($this->tokens[$stackPtr]['content']) !== 'function' + ) { + // This is a function declared without the "function" keyword. + // So this token is the function name. + return $this->tokens[$stackPtr]['content']; + } + + $content = null; + for ($i = $stackPtr; $i < $this->numTokens; $i++) { + if ($this->tokens[$i]['code'] === T_STRING) { + $content = $this->tokens[$i]['content']; + break; + } + } + + return $content; + + }//end getDeclarationName() + + + /** + * Returns the method parameters for the specified function token. + * + * Also supports passing in a USE token for a closure use group. + * + * Each parameter is in the following format: + * + * + * 0 => array( + * 'name' => '$var', // The variable name. + * 'token' => integer, // The stack pointer to the variable name. + * 'content' => string, // The full content of the variable definition. + * 'has_attributes' => boolean, // Does the parameter have one or more attributes attached ? + * 'pass_by_reference' => boolean, // Is the variable passed by reference? + * 'reference_token' => integer, // The stack pointer to the reference operator + * // or FALSE if the param is not passed by reference. + * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? + * 'variadic_token' => integer, // The stack pointer to the ... operator + * // or FALSE if the param is not variable length. + * 'type_hint' => string, // The type hint for the variable. + * 'type_hint_token' => integer, // The stack pointer to the start of the type hint + * // or FALSE if there is no type hint. + * 'type_hint_end_token' => integer, // The stack pointer to the end of the type hint + * // or FALSE if there is no type hint. + * 'nullable_type' => boolean, // TRUE if the type is preceded by the nullability + * // operator. + * 'comma_token' => integer, // The stack pointer to the comma after the param + * // or FALSE if this is the last param. + * ) + * + * + * Parameters with default values have additional array indexes of: + * 'default' => string, // The full content of the default value. + * 'default_token' => integer, // The stack pointer to the start of the default value. + * 'default_equal_token' => integer, // The stack pointer to the equals sign. + * + * Parameters declared using PHP 8 constructor property promotion, have these additional array indexes: + * 'property_visibility' => string, // The property visibility as declared. + * 'visibility_token' => integer, // The stack pointer to the visibility modifier token. + * 'property_readonly' => bool, // TRUE if the readonly keyword was found. + * 'readonly_token' => integer, // The stack pointer to the readonly modifier token. + * + * @param int $stackPtr The position in the stack of the function token + * to acquire the parameters for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified $stackPtr is not of + * type T_FUNCTION, T_CLOSURE, T_USE, + * or T_FN. + */ + public function getMethodParameters($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_CLOSURE + && $this->tokens[$stackPtr]['code'] !== T_USE + && $this->tokens[$stackPtr]['code'] !== T_FN + ) { + throw new RuntimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_USE or T_FN'); + } + + if ($this->tokens[$stackPtr]['code'] === T_USE) { + $opener = $this->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1)); + if ($opener === false || isset($this->tokens[$opener]['parenthesis_owner']) === true) { + throw new RuntimeException('$stackPtr was not a valid T_USE'); + } + } else { + if (isset($this->tokens[$stackPtr]['parenthesis_opener']) === false) { + // Live coding or syntax error, so no params to find. + return []; + } + + $opener = $this->tokens[$stackPtr]['parenthesis_opener']; + } + + if (isset($this->tokens[$opener]['parenthesis_closer']) === false) { + // Live coding or syntax error, so no params to find. + return []; + } + + $closer = $this->tokens[$opener]['parenthesis_closer']; + + $vars = []; + $currVar = null; + $paramStart = ($opener + 1); + $defaultStart = null; + $equalToken = null; + $paramCount = 0; + $hasAttributes = false; + $passByReference = false; + $referenceToken = false; + $variableLength = false; + $variadicToken = false; + $typeHint = ''; + $typeHintToken = false; + $typeHintEndToken = false; + $nullableType = false; + $visibilityToken = null; + $readonlyToken = null; + + for ($i = $paramStart; $i <= $closer; $i++) { + // Check to see if this token has a parenthesis or bracket opener. If it does + // it's likely to be an array which might have arguments in it. This + // could cause problems in our parsing below, so lets just skip to the + // end of it. + if (isset($this->tokens[$i]['parenthesis_opener']) === true) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $this->tokens[$i]['parenthesis_closer']) { + $i = $this->tokens[$i]['parenthesis_closer']; + continue; + } + } + + if (isset($this->tokens[$i]['bracket_opener']) === true) { + if ($i !== $this->tokens[$i]['bracket_closer']) { + $i = $this->tokens[$i]['bracket_closer']; + continue; + } + } + + switch ($this->tokens[$i]['code']) { + case T_ATTRIBUTE: + $hasAttributes = true; + + // Skip to the end of the attribute. + $i = $this->tokens[$i]['attribute_closer']; + break; + case T_BITWISE_AND: + if ($defaultStart === null) { + $passByReference = true; + $referenceToken = $i; + } + break; + case T_VARIABLE: + $currVar = $i; + break; + case T_ELLIPSIS: + $variableLength = true; + $variadicToken = $i; + break; + case T_CALLABLE: + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + break; + case T_SELF: + case T_PARENT: + case T_STATIC: + // Self and parent are valid, static invalid, but was probably intended as type hint. + if (isset($defaultStart) === false) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_STRING: + // This is a string, so it may be a type hint, but it could + // also be a constant used as a default value. + $prevComma = false; + for ($t = $i; $t >= $opener; $t--) { + if ($this->tokens[$t]['code'] === T_COMMA) { + $prevComma = $t; + break; + } + } + + if ($prevComma !== false) { + $nextEquals = false; + for ($t = $prevComma; $t < $i; $t++) { + if ($this->tokens[$t]['code'] === T_EQUAL) { + $nextEquals = $t; + break; + } + } + + if ($nextEquals !== false) { + break; + } + } + + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_NAMESPACE: + case T_NS_SEPARATOR: + case T_TYPE_UNION: + case T_TYPE_INTERSECTION: + case T_FALSE: + case T_NULL: + // Part of a type hint or default value. + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_NULLABLE: + if ($defaultStart === null) { + $nullableType = true; + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_PUBLIC: + case T_PROTECTED: + case T_PRIVATE: + if ($defaultStart === null) { + $visibilityToken = $i; + } + break; + case T_READONLY: + if ($defaultStart === null) { + $readonlyToken = $i; + } + break; + case T_CLOSE_PARENTHESIS: + case T_COMMA: + // If it's null, then there must be no parameters for this + // method. + if ($currVar === null) { + continue 2; + } + + $vars[$paramCount] = []; + $vars[$paramCount]['token'] = $currVar; + $vars[$paramCount]['name'] = $this->tokens[$currVar]['content']; + $vars[$paramCount]['content'] = trim($this->getTokensAsString($paramStart, ($i - $paramStart))); + + if ($defaultStart !== null) { + $vars[$paramCount]['default'] = trim($this->getTokensAsString($defaultStart, ($i - $defaultStart))); + $vars[$paramCount]['default_token'] = $defaultStart; + $vars[$paramCount]['default_equal_token'] = $equalToken; + } + + $vars[$paramCount]['has_attributes'] = $hasAttributes; + $vars[$paramCount]['pass_by_reference'] = $passByReference; + $vars[$paramCount]['reference_token'] = $referenceToken; + $vars[$paramCount]['variable_length'] = $variableLength; + $vars[$paramCount]['variadic_token'] = $variadicToken; + $vars[$paramCount]['type_hint'] = $typeHint; + $vars[$paramCount]['type_hint_token'] = $typeHintToken; + $vars[$paramCount]['type_hint_end_token'] = $typeHintEndToken; + $vars[$paramCount]['nullable_type'] = $nullableType; + + if ($visibilityToken !== null) { + $vars[$paramCount]['property_visibility'] = $this->tokens[$visibilityToken]['content']; + $vars[$paramCount]['visibility_token'] = $visibilityToken; + $vars[$paramCount]['property_readonly'] = false; + } + + if ($readonlyToken !== null) { + $vars[$paramCount]['property_readonly'] = true; + $vars[$paramCount]['readonly_token'] = $readonlyToken; + } + + if ($this->tokens[$i]['code'] === T_COMMA) { + $vars[$paramCount]['comma_token'] = $i; + } else { + $vars[$paramCount]['comma_token'] = false; + } + + // Reset the vars, as we are about to process the next parameter. + $currVar = null; + $paramStart = ($i + 1); + $defaultStart = null; + $equalToken = null; + $hasAttributes = false; + $passByReference = false; + $referenceToken = false; + $variableLength = false; + $variadicToken = false; + $typeHint = ''; + $typeHintToken = false; + $typeHintEndToken = false; + $nullableType = false; + $visibilityToken = null; + $readonlyToken = null; + + $paramCount++; + break; + case T_EQUAL: + $defaultStart = $this->findNext(Util\Tokens::$emptyTokens, ($i + 1), null, true); + $equalToken = $i; + break; + }//end switch + }//end for + + return $vars; + + }//end getMethodParameters() + + + /** + * Returns the visibility and implementation properties of a method. + * + * The format of the return value is: + * + * array( + * 'scope' => 'public', // Public, private, or protected + * 'scope_specified' => true, // TRUE if the scope keyword was found. + * 'return_type' => '', // The return type of the method. + * 'return_type_token' => integer, // The stack pointer to the start of the return type + * // or FALSE if there is no return type. + * 'return_type_end_token' => integer, // The stack pointer to the end of the return type + * // or FALSE if there is no return type. + * 'nullable_return_type' => false, // TRUE if the return type is preceded by the + * // nullability operator. + * 'is_abstract' => false, // TRUE if the abstract keyword was found. + * 'is_final' => false, // TRUE if the final keyword was found. + * 'is_static' => false, // TRUE if the static keyword was found. + * 'has_body' => false, // TRUE if the method has a body + * ); + * + * + * @param int $stackPtr The position in the stack of the function token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_FUNCTION, T_CLOSURE, or T_FN token. + */ + public function getMethodProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_CLOSURE + && $this->tokens[$stackPtr]['code'] !== T_FN + ) { + throw new RuntimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_FN'); + } + + if ($this->tokens[$stackPtr]['code'] === T_FUNCTION) { + $valid = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_STATIC => T_STATIC, + T_FINAL => T_FINAL, + T_ABSTRACT => T_ABSTRACT, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + } else { + $valid = [ + T_STATIC => T_STATIC, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + } + + $scope = 'public'; + $scopeSpecified = false; + $isAbstract = false; + $isFinal = false; + $isStatic = false; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_PUBLIC: + $scope = 'public'; + $scopeSpecified = true; + break; + case T_PRIVATE: + $scope = 'private'; + $scopeSpecified = true; + break; + case T_PROTECTED: + $scope = 'protected'; + $scopeSpecified = true; + break; + case T_ABSTRACT: + $isAbstract = true; + break; + case T_FINAL: + $isFinal = true; + break; + case T_STATIC: + $isStatic = true; + break; + }//end switch + }//end for + + $returnType = ''; + $returnTypeToken = false; + $returnTypeEndToken = false; + $nullableReturnType = false; + $hasBody = true; + + if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true) { + $scopeOpener = null; + if (isset($this->tokens[$stackPtr]['scope_opener']) === true) { + $scopeOpener = $this->tokens[$stackPtr]['scope_opener']; + } + + $valid = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + T_FALSE => T_FALSE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + ]; + + for ($i = $this->tokens[$stackPtr]['parenthesis_closer']; $i < $this->numTokens; $i++) { + if (($scopeOpener === null && $this->tokens[$i]['code'] === T_SEMICOLON) + || ($scopeOpener !== null && $i === $scopeOpener) + ) { + // End of function definition. + break; + } + + if ($this->tokens[$i]['code'] === T_NULLABLE) { + $nullableReturnType = true; + } + + if (isset($valid[$this->tokens[$i]['code']]) === true) { + if ($returnTypeToken === false) { + $returnTypeToken = $i; + } + + $returnType .= $this->tokens[$i]['content']; + $returnTypeEndToken = $i; + } + }//end for + + if ($this->tokens[$stackPtr]['code'] === T_FN) { + $bodyToken = T_FN_ARROW; + } else { + $bodyToken = T_OPEN_CURLY_BRACKET; + } + + $end = $this->findNext([$bodyToken, T_SEMICOLON], $this->tokens[$stackPtr]['parenthesis_closer']); + $hasBody = $this->tokens[$end]['code'] === $bodyToken; + }//end if + + if ($returnType !== '' && $nullableReturnType === true) { + $returnType = '?'.$returnType; + } + + return [ + 'scope' => $scope, + 'scope_specified' => $scopeSpecified, + 'return_type' => $returnType, + 'return_type_token' => $returnTypeToken, + 'return_type_end_token' => $returnTypeEndToken, + 'nullable_return_type' => $nullableReturnType, + 'is_abstract' => $isAbstract, + 'is_final' => $isFinal, + 'is_static' => $isStatic, + 'has_body' => $hasBody, + ]; + + }//end getMethodProperties() + + + /** + * Returns the visibility and implementation properties of a class member var. + * + * The format of the return value is: + * + * + * array( + * 'scope' => string, // Public, private, or protected. + * 'scope_specified' => boolean, // TRUE if the scope was explicitly specified. + * 'is_static' => boolean, // TRUE if the static keyword was found. + * 'is_readonly' => boolean, // TRUE if the readonly keyword was found. + * 'type' => string, // The type of the var (empty if no type specified). + * 'type_token' => integer, // The stack pointer to the start of the type + * // or FALSE if there is no type. + * 'type_end_token' => integer, // The stack pointer to the end of the type + * // or FALSE if there is no type. + * 'nullable_type' => boolean, // TRUE if the type is preceded by the nullability + * // operator. + * ); + * + * + * @param int $stackPtr The position in the stack of the T_VARIABLE token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_VARIABLE token, or if the position is not + * a class member variable. + */ + public function getMemberProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_VARIABLE) { + throw new RuntimeException('$stackPtr must be of type T_VARIABLE'); + } + + $conditions = array_keys($this->tokens[$stackPtr]['conditions']); + $ptr = array_pop($conditions); + if (isset($this->tokens[$ptr]) === false + || ($this->tokens[$ptr]['code'] !== T_CLASS + && $this->tokens[$ptr]['code'] !== T_ANON_CLASS + && $this->tokens[$ptr]['code'] !== T_TRAIT) + ) { + if (isset($this->tokens[$ptr]) === true + && ($this->tokens[$ptr]['code'] === T_INTERFACE + || $this->tokens[$ptr]['code'] === T_ENUM) + ) { + // T_VARIABLEs in interfaces/enums can actually be method arguments + // but they wont be seen as being inside the method because there + // are no scope openers and closers for abstract methods. If it is in + // parentheses, we can be pretty sure it is a method argument. + if (isset($this->tokens[$stackPtr]['nested_parenthesis']) === false + || empty($this->tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $error = 'Possible parse error: %ss may not include member vars'; + $code = sprintf('Internal.ParseError.%sHasMemberVar', ucfirst($this->tokens[$ptr]['content'])); + $data = [strtolower($this->tokens[$ptr]['content'])]; + $this->addWarning($error, $stackPtr, $code, $data); + return []; + } + } else { + throw new RuntimeException('$stackPtr is not a class member var'); + } + }//end if + + // Make sure it's not a method parameter. + if (empty($this->tokens[$stackPtr]['nested_parenthesis']) === false) { + $parenthesis = array_keys($this->tokens[$stackPtr]['nested_parenthesis']); + $deepestOpen = array_pop($parenthesis); + if ($deepestOpen > $ptr + && isset($this->tokens[$deepestOpen]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$deepestOpen]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + throw new RuntimeException('$stackPtr is not a class member var'); + } + } + + $valid = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_STATIC => T_STATIC, + T_VAR => T_VAR, + T_READONLY => T_READONLY, + ]; + + $valid += Util\Tokens::$emptyTokens; + + $scope = 'public'; + $scopeSpecified = false; + $isStatic = false; + $isReadonly = false; + + $startOfStatement = $this->findPrevious( + [ + T_SEMICOLON, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + T_ATTRIBUTE_END, + ], + ($stackPtr - 1) + ); + + for ($i = ($startOfStatement + 1); $i < $stackPtr; $i++) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_PUBLIC: + $scope = 'public'; + $scopeSpecified = true; + break; + case T_PRIVATE: + $scope = 'private'; + $scopeSpecified = true; + break; + case T_PROTECTED: + $scope = 'protected'; + $scopeSpecified = true; + break; + case T_STATIC: + $isStatic = true; + break; + case T_READONLY: + $isReadonly = true; + break; + } + }//end for + + $type = ''; + $typeToken = false; + $typeEndToken = false; + $nullableType = false; + + if ($i < $stackPtr) { + // We've found a type. + $valid = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_FALSE => T_FALSE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + ]; + + for ($i; $i < $stackPtr; $i++) { + if ($this->tokens[$i]['code'] === T_VARIABLE) { + // Hit another variable in a group definition. + break; + } + + if ($this->tokens[$i]['code'] === T_NULLABLE) { + $nullableType = true; + } + + if (isset($valid[$this->tokens[$i]['code']]) === true) { + $typeEndToken = $i; + if ($typeToken === false) { + $typeToken = $i; + } + + $type .= $this->tokens[$i]['content']; + } + } + + if ($type !== '' && $nullableType === true) { + $type = '?'.$type; + } + }//end if + + return [ + 'scope' => $scope, + 'scope_specified' => $scopeSpecified, + 'is_static' => $isStatic, + 'is_readonly' => $isReadonly, + 'type' => $type, + 'type_token' => $typeToken, + 'type_end_token' => $typeEndToken, + 'nullable_type' => $nullableType, + ]; + + }//end getMemberProperties() + + + /** + * Returns the visibility and implementation properties of a class. + * + * The format of the return value is: + * + * array( + * 'is_abstract' => false, // true if the abstract keyword was found. + * 'is_final' => false, // true if the final keyword was found. + * ); + * + * + * @param int $stackPtr The position in the stack of the T_CLASS token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_CLASS token. + */ + public function getClassProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_CLASS) { + throw new RuntimeException('$stackPtr must be of type T_CLASS'); + } + + $valid = [ + T_FINAL => T_FINAL, + T_ABSTRACT => T_ABSTRACT, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + + $isAbstract = false; + $isFinal = false; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_ABSTRACT: + $isAbstract = true; + break; + + case T_FINAL: + $isFinal = true; + break; + } + }//end for + + return [ + 'is_abstract' => $isAbstract, + 'is_final' => $isFinal, + ]; + + }//end getClassProperties() + + + /** + * Determine if the passed token is a reference operator. + * + * Returns true if the specified token position represents a reference. + * Returns false if the token represents a bitwise operator. + * + * @param int $stackPtr The position of the T_BITWISE_AND token. + * + * @return boolean + */ + public function isReference($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_BITWISE_AND) { + return false; + } + + $tokenBefore = $this->findPrevious( + Util\Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($this->tokens[$tokenBefore]['code'] === T_FUNCTION + || $this->tokens[$tokenBefore]['code'] === T_CLOSURE + || $this->tokens[$tokenBefore]['code'] === T_FN + ) { + // Function returns a reference. + return true; + } + + if ($this->tokens[$tokenBefore]['code'] === T_DOUBLE_ARROW) { + // Inside a foreach loop or array assignment, this is a reference. + return true; + } + + if ($this->tokens[$tokenBefore]['code'] === T_AS) { + // Inside a foreach loop, this is a reference. + return true; + } + + if (isset(Util\Tokens::$assignmentTokens[$this->tokens[$tokenBefore]['code']]) === true) { + // This is directly after an assignment. It's a reference. Even if + // it is part of an operation, the other tests will handle it. + return true; + } + + $tokenAfter = $this->findNext( + Util\Tokens::$emptyTokens, + ($stackPtr + 1), + null, + true + ); + + if ($this->tokens[$tokenAfter]['code'] === T_NEW) { + return true; + } + + if (isset($this->tokens[$stackPtr]['nested_parenthesis']) === true) { + $brackets = $this->tokens[$stackPtr]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if (isset($this->tokens[$lastBracket]['parenthesis_owner']) === true) { + $owner = $this->tokens[$this->tokens[$lastBracket]['parenthesis_owner']]; + if ($owner['code'] === T_FUNCTION + || $owner['code'] === T_CLOSURE + || $owner['code'] === T_FN + ) { + $params = $this->getMethodParameters($this->tokens[$lastBracket]['parenthesis_owner']); + foreach ($params as $param) { + if ($param['reference_token'] === $stackPtr) { + // Function parameter declared to be passed by reference. + return true; + } + } + }//end if + } else { + $prev = false; + for ($t = ($this->tokens[$lastBracket]['parenthesis_opener'] - 1); $t >= 0; $t--) { + if ($this->tokens[$t]['code'] !== T_WHITESPACE) { + $prev = $t; + break; + } + } + + if ($prev !== false && $this->tokens[$prev]['code'] === T_USE) { + // Closure use by reference. + return true; + } + }//end if + }//end if + + // Pass by reference in function calls and assign by reference in arrays. + if ($this->tokens[$tokenBefore]['code'] === T_OPEN_PARENTHESIS + || $this->tokens[$tokenBefore]['code'] === T_COMMA + || $this->tokens[$tokenBefore]['code'] === T_OPEN_SHORT_ARRAY + ) { + if ($this->tokens[$tokenAfter]['code'] === T_VARIABLE) { + return true; + } else { + $skip = Util\Tokens::$emptyTokens; + $skip[] = T_NS_SEPARATOR; + $skip[] = T_SELF; + $skip[] = T_PARENT; + $skip[] = T_STATIC; + $skip[] = T_STRING; + $skip[] = T_NAMESPACE; + $skip[] = T_DOUBLE_COLON; + + $nextSignificantAfter = $this->findNext( + $skip, + ($stackPtr + 1), + null, + true + ); + if ($this->tokens[$nextSignificantAfter]['code'] === T_VARIABLE) { + return true; + } + }//end if + }//end if + + return false; + + }//end isReference() + + + /** + * Returns the content of the tokens from the specified start position in + * the token stack for the specified length. + * + * @param int $start The position to start from in the token stack. + * @param int $length The length of tokens to traverse from the start pos. + * @param bool $origContent Whether the original content or the tab replaced + * content should be used. + * + * @return string The token contents. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position does not exist. + */ + public function getTokensAsString($start, $length, $origContent=false) + { + if (is_int($start) === false || isset($this->tokens[$start]) === false) { + throw new RuntimeException('The $start position for getTokensAsString() must exist in the token stack'); + } + + if (is_int($length) === false || $length <= 0) { + return ''; + } + + $str = ''; + $end = ($start + $length); + if ($end > $this->numTokens) { + $end = $this->numTokens; + } + + for ($i = $start; $i < $end; $i++) { + // If tabs are being converted to spaces by the tokeniser, the + // original content should be used instead of the converted content. + if ($origContent === true && isset($this->tokens[$i]['orig_content']) === true) { + $str .= $this->tokens[$i]['orig_content']; + } else { + $str .= $this->tokens[$i]['content']; + } + } + + return $str; + + }//end getTokensAsString() + + + /** + * Returns the position of the previous specified token(s). + * + * If a value is specified, the previous token of the specified type(s) + * containing the specified value will be returned. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param int|null $end The end position to fail if no token is found. + * if not specified or null, end will default to + * the start of the token stack. + * @param bool $exclude If true, find the previous token that is NOT of + * the types specified in $types. + * @param string|null $value The value that the token(s) must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * @param bool $local If true, tokens outside the current statement + * will not be checked. IE. checking will stop + * at the previous semi-colon found. + * + * @return int|false + * @see findNext() + */ + public function findPrevious( + $types, + $start, + $end=null, + $exclude=false, + $value=null, + $local=false + ) { + $types = (array) $types; + + if ($end === null) { + $end = 0; + } + + for ($i = $start; $i >= $end; $i--) { + $found = (bool) $exclude; + foreach ($types as $type) { + if ($this->tokens[$i]['code'] === $type) { + $found = !$exclude; + break; + } + } + + if ($found === true) { + if ($value === null) { + return $i; + } else if ($this->tokens[$i]['content'] === $value) { + return $i; + } + } + + if ($local === true) { + if (isset($this->tokens[$i]['scope_opener']) === true + && $i === $this->tokens[$i]['scope_closer'] + ) { + $i = $this->tokens[$i]['scope_opener']; + } else if (isset($this->tokens[$i]['bracket_opener']) === true + && $i === $this->tokens[$i]['bracket_closer'] + ) { + $i = $this->tokens[$i]['bracket_opener']; + } else if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + $i = $this->tokens[$i]['parenthesis_opener']; + } else if ($this->tokens[$i]['code'] === T_SEMICOLON) { + break; + } + } + }//end for + + return false; + + }//end findPrevious() + + + /** + * Returns the position of the next specified token(s). + * + * If a value is specified, the next token of the specified type(s) + * containing the specified value will be returned. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param int|null $end The end position to fail if no token is found. + * if not specified or null, end will default to + * the end of the token stack. + * @param bool $exclude If true, find the next token that is NOT of + * a type specified in $types. + * @param string|null $value The value that the token(s) must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * @param bool $local If true, tokens outside the current statement + * will not be checked. i.e., checking will stop + * at the next semi-colon found. + * + * @return int|false + * @see findPrevious() + */ + public function findNext( + $types, + $start, + $end=null, + $exclude=false, + $value=null, + $local=false + ) { + $types = (array) $types; + + if ($end === null || $end > $this->numTokens) { + $end = $this->numTokens; + } + + for ($i = $start; $i < $end; $i++) { + $found = (bool) $exclude; + foreach ($types as $type) { + if ($this->tokens[$i]['code'] === $type) { + $found = !$exclude; + break; + } + } + + if ($found === true) { + if ($value === null) { + return $i; + } else if ($this->tokens[$i]['content'] === $value) { + return $i; + } + } + + if ($local === true && $this->tokens[$i]['code'] === T_SEMICOLON) { + break; + } + }//end for + + return false; + + }//end findNext() + + + /** + * Returns the position of the first non-whitespace token in a statement. + * + * @param int $start The position to start searching from in the token stack. + * @param int|string|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public function findStartOfStatement($start, $ignore=null) + { + $startTokens = Util\Tokens::$blockOpeners; + $startTokens[T_OPEN_SHORT_ARRAY] = true; + $startTokens[T_OPEN_TAG] = true; + $startTokens[T_OPEN_TAG_WITH_ECHO] = true; + + $endTokens = [ + T_CLOSE_TAG => true, + T_COLON => true, + T_COMMA => true, + T_DOUBLE_ARROW => true, + T_MATCH_ARROW => true, + T_SEMICOLON => true, + ]; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($startTokens[$code]) === true) { + unset($startTokens[$code]); + } + + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + // If the start token is inside the case part of a match expression, + // find the start of the condition. If it's in the statement part, find + // the token that comes after the match arrow. + $matchExpression = $this->getCondition($start, T_MATCH); + if ($matchExpression !== false) { + for ($prevMatch = $start; $prevMatch > $this->tokens[$matchExpression]['scope_opener']; $prevMatch--) { + if ($prevMatch !== $start + && ($this->tokens[$prevMatch]['code'] === T_MATCH_ARROW + || $this->tokens[$prevMatch]['code'] === T_COMMA) + ) { + break; + } + + // Skip nested statements. + if (isset($this->tokens[$prevMatch]['bracket_opener']) === true + && $prevMatch === $this->tokens[$prevMatch]['bracket_closer'] + ) { + $prevMatch = $this->tokens[$prevMatch]['bracket_opener']; + } else if (isset($this->tokens[$prevMatch]['parenthesis_opener']) === true + && $prevMatch === $this->tokens[$prevMatch]['parenthesis_closer'] + ) { + $prevMatch = $this->tokens[$prevMatch]['parenthesis_opener']; + } + } + + if ($prevMatch <= $this->tokens[$matchExpression]['scope_opener']) { + // We're before the arrow in the first case. + $next = $this->findNext(Util\Tokens::$emptyTokens, ($this->tokens[$matchExpression]['scope_opener'] + 1), null, true); + if ($next === false) { + return $start; + } + + return $next; + } + + if ($this->tokens[$prevMatch]['code'] === T_COMMA) { + // We're before the arrow, but not in the first case. + $prevMatchArrow = $this->findPrevious(T_MATCH_ARROW, ($prevMatch - 1), $this->tokens[$matchExpression]['scope_opener']); + if ($prevMatchArrow === false) { + // We're before the arrow in the first case. + $next = $this->findNext(Util\Tokens::$emptyTokens, ($this->tokens[$matchExpression]['scope_opener'] + 1), null, true); + return $next; + } + + $end = $this->findEndOfStatement($prevMatchArrow); + $next = $this->findNext(Util\Tokens::$emptyTokens, ($end + 1), null, true); + return $next; + } + }//end if + + $lastNotEmpty = $start; + + // If we are starting at a token that ends a scope block, skip to + // the start and continue from there. + // If we are starting at a token that ends a statement, skip this + // token so we find the true start of the statement. + while (isset($endTokens[$this->tokens[$start]['code']]) === true + || (isset($this->tokens[$start]['scope_condition']) === true + && $start === $this->tokens[$start]['scope_closer']) + ) { + if (isset($this->tokens[$start]['scope_condition']) === true) { + $start = $this->tokens[$start]['scope_condition']; + } else { + $start--; + } + } + + for ($i = $start; $i >= 0; $i--) { + if (isset($startTokens[$this->tokens[$i]['code']]) === true + || isset($endTokens[$this->tokens[$i]['code']]) === true + ) { + // Found the end of the previous statement. + return $lastNotEmpty; + } + + if (isset($this->tokens[$i]['scope_opener']) === true + && $i === $this->tokens[$i]['scope_closer'] + && $this->tokens[$i]['code'] !== T_CLOSE_PARENTHESIS + && $this->tokens[$i]['code'] !== T_END_NOWDOC + && $this->tokens[$i]['code'] !== T_END_HEREDOC + && $this->tokens[$i]['code'] !== T_BREAK + && $this->tokens[$i]['code'] !== T_RETURN + && $this->tokens[$i]['code'] !== T_CONTINUE + && $this->tokens[$i]['code'] !== T_THROW + && $this->tokens[$i]['code'] !== T_EXIT + ) { + // Found the end of the previous scope block. + return $lastNotEmpty; + } + + // Skip nested statements. + if (isset($this->tokens[$i]['bracket_opener']) === true + && $i === $this->tokens[$i]['bracket_closer'] + ) { + $i = $this->tokens[$i]['bracket_opener']; + } else if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + $i = $this->tokens[$i]['parenthesis_opener']; + } else if ($this->tokens[$i]['code'] === T_CLOSE_USE_GROUP) { + $start = $this->findPrevious(T_OPEN_USE_GROUP, ($i - 1)); + if ($start !== false) { + $i = $start; + } + }//end if + + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return 0; + + }//end findStartOfStatement() + + + /** + * Returns the position of the last non-whitespace token in a statement. + * + * @param int $start The position to start searching from in the token stack. + * @param int|string|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public function findEndOfStatement($start, $ignore=null) + { + $endTokens = [ + T_COLON => true, + T_COMMA => true, + T_DOUBLE_ARROW => true, + T_SEMICOLON => true, + T_CLOSE_PARENTHESIS => true, + T_CLOSE_SQUARE_BRACKET => true, + T_CLOSE_CURLY_BRACKET => true, + T_CLOSE_SHORT_ARRAY => true, + T_OPEN_TAG => true, + T_CLOSE_TAG => true, + ]; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + unset($endTokens[$code]); + } + } + + // If the start token is inside the case part of a match expression, + // advance to the match arrow and continue looking for the + // end of the statement from there so that we skip over commas. + if ($this->tokens[$start]['code'] !== T_MATCH_ARROW) { + $matchExpression = $this->getCondition($start, T_MATCH); + if ($matchExpression !== false) { + $beforeArrow = true; + $prevMatchArrow = $this->findPrevious(T_MATCH_ARROW, ($start - 1), $this->tokens[$matchExpression]['scope_opener']); + if ($prevMatchArrow !== false) { + $prevComma = $this->findNext(T_COMMA, ($prevMatchArrow + 1), $start); + if ($prevComma === false) { + // No comma between this token and the last match arrow, + // so this token exists after the arrow and we can continue + // checking as normal. + $beforeArrow = false; + } + } + + if ($beforeArrow === true) { + $nextMatchArrow = $this->findNext(T_MATCH_ARROW, ($start + 1), $this->tokens[$matchExpression]['scope_closer']); + if ($nextMatchArrow !== false) { + $start = $nextMatchArrow; + } + } + }//end if + }//end if + + $lastNotEmpty = $start; + for ($i = $start; $i < $this->numTokens; $i++) { + if ($i !== $start && isset($endTokens[$this->tokens[$i]['code']]) === true) { + // Found the end of the statement. + if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS + || $this->tokens[$i]['code'] === T_CLOSE_SQUARE_BRACKET + || $this->tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + || $this->tokens[$i]['code'] === T_CLOSE_SHORT_ARRAY + || $this->tokens[$i]['code'] === T_OPEN_TAG + || $this->tokens[$i]['code'] === T_CLOSE_TAG + ) { + return $lastNotEmpty; + } + + return $i; + } + + // Skip nested statements. + if (isset($this->tokens[$i]['scope_closer']) === true + && ($i === $this->tokens[$i]['scope_opener'] + || $i === $this->tokens[$i]['scope_condition']) + ) { + if ($this->tokens[$i]['code'] === T_FN) { + $lastNotEmpty = $this->tokens[$i]['scope_closer']; + $i = ($this->tokens[$i]['scope_closer'] - 1); + continue; + } + + if ($i === $start && isset(Util\Tokens::$scopeOpeners[$this->tokens[$i]['code']]) === true) { + return $this->tokens[$i]['scope_closer']; + } + + $i = $this->tokens[$i]['scope_closer']; + } else if (isset($this->tokens[$i]['bracket_closer']) === true + && $i === $this->tokens[$i]['bracket_opener'] + ) { + $i = $this->tokens[$i]['bracket_closer']; + } else if (isset($this->tokens[$i]['parenthesis_closer']) === true + && $i === $this->tokens[$i]['parenthesis_opener'] + ) { + $i = $this->tokens[$i]['parenthesis_closer']; + } else if ($this->tokens[$i]['code'] === T_OPEN_USE_GROUP) { + $end = $this->findNext(T_CLOSE_USE_GROUP, ($i + 1)); + if ($end !== false) { + $i = $end; + } + }//end if + + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return ($this->numTokens - 1); + + }//end findEndOfStatement() + + + /** + * Returns the position of the first token on a line, matching given type. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. The first token matching on + * this line before this token will be returned. + * @param bool $exclude If true, find the token that is NOT of + * the types specified in $types. + * @param string $value The value that the token must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * + * @return int|false + */ + public function findFirstOnLine($types, $start, $exclude=false, $value=null) + { + if (is_array($types) === false) { + $types = [$types]; + } + + $foundToken = false; + + for ($i = $start; $i >= 0; $i--) { + if ($this->tokens[$i]['line'] < $this->tokens[$start]['line']) { + break; + } + + $found = $exclude; + foreach ($types as $type) { + if ($exclude === false) { + if ($this->tokens[$i]['code'] === $type) { + $found = true; + break; + } + } else { + if ($this->tokens[$i]['code'] === $type) { + $found = false; + break; + } + } + } + + if ($found === true) { + if ($value === null) { + $foundToken = $i; + } else if ($this->tokens[$i]['content'] === $value) { + $foundToken = $i; + } + } + }//end for + + return $foundToken; + + }//end findFirstOnLine() + + + /** + * Determine if the passed token has a condition of one of the passed types. + * + * @param int $stackPtr The position of the token we are checking. + * @param int|string|array $types The type(s) of tokens to search for. + * + * @return boolean + */ + public function hasCondition($stackPtr, $types) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + // Make sure the token has conditions. + if (isset($this->tokens[$stackPtr]['conditions']) === false) { + return false; + } + + $types = (array) $types; + $conditions = $this->tokens[$stackPtr]['conditions']; + + foreach ($types as $type) { + if (in_array($type, $conditions, true) === true) { + // We found a token with the required type. + return true; + } + } + + return false; + + }//end hasCondition() + + + /** + * Return the position of the condition for the passed token. + * + * Returns FALSE if the token does not have the condition. + * + * @param int $stackPtr The position of the token we are checking. + * @param int|string $type The type of token to search for. + * @param bool $first If TRUE, will return the matched condition + * furthest away from the passed token. + * If FALSE, will return the matched condition + * closest to the passed token. + * + * @return int|false + */ + public function getCondition($stackPtr, $type, $first=true) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + // Make sure the token has conditions. + if (isset($this->tokens[$stackPtr]['conditions']) === false) { + return false; + } + + $conditions = $this->tokens[$stackPtr]['conditions']; + if ($first === false) { + $conditions = array_reverse($conditions, true); + } + + foreach ($conditions as $token => $condition) { + if ($condition === $type) { + return $token; + } + } + + return false; + + }//end getCondition() + + + /** + * Returns the name of the class that the specified class extends. + * (works for classes, anonymous classes and interfaces) + * + * Returns FALSE on error or if there is no extended class name. + * + * @param int $stackPtr The stack position of the class. + * + * @return string|false + */ + public function findExtendedClassName($stackPtr) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + if ($this->tokens[$stackPtr]['code'] !== T_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ANON_CLASS + && $this->tokens[$stackPtr]['code'] !== T_INTERFACE + ) { + return false; + } + + if (isset($this->tokens[$stackPtr]['scope_opener']) === false) { + return false; + } + + $classOpenerIndex = $this->tokens[$stackPtr]['scope_opener']; + $extendsIndex = $this->findNext(T_EXTENDS, $stackPtr, $classOpenerIndex); + if ($extendsIndex === false) { + return false; + } + + $find = [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + ]; + + $end = $this->findNext($find, ($extendsIndex + 1), ($classOpenerIndex + 1), true); + $name = $this->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } + + return $name; + + }//end findExtendedClassName() + + + /** + * Returns the names of the interfaces that the specified class or enum implements. + * + * Returns FALSE on error or if there are no implemented interface names. + * + * @param int $stackPtr The stack position of the class or enum token. + * + * @return array|false + */ + public function findImplementedInterfaceNames($stackPtr) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + if ($this->tokens[$stackPtr]['code'] !== T_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ANON_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ENUM + ) { + return false; + } + + if (isset($this->tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classOpenerIndex = $this->tokens[$stackPtr]['scope_opener']; + $implementsIndex = $this->findNext(T_IMPLEMENTS, $stackPtr, $classOpenerIndex); + if ($implementsIndex === false) { + return false; + } + + $find = [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + T_COMMA, + ]; + + $end = $this->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); + $name = $this->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } else { + $names = explode(',', $name); + $names = array_map('trim', $names); + return $names; + } + + }//end findImplementedInterfaceNames() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Files/FileList.php b/kirki-composer/squizlabs/php_codesniffer/src/Files/FileList.php new file mode 100644 index 000000000..66833a3ee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Files/FileList.php @@ -0,0 +1,255 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\DeepExitException; +use ReturnTypeWillChange; + +class FileList implements \Iterator, \Countable +{ + + /** + * A list of file paths that are included in the list. + * + * @var array + */ + private $files = []; + + /** + * The number of files in the list. + * + * @var integer + */ + private $numFiles = 0; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * An array of patterns to use for skipping files. + * + * @var array + */ + protected $ignorePatterns = []; + + + /** + * Constructs a file list and loads in an array of file paths to process. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @return void + */ + public function __construct(Config $config, Ruleset $ruleset) + { + $this->ruleset = $ruleset; + $this->config = $config; + + $paths = $config->files; + foreach ($paths as $path) { + $isPharFile = Util\Common::isPharFile($path); + if (is_dir($path) === true || $isPharFile === true) { + if ($isPharFile === true) { + $path = 'phar://'.$path; + } + + $filterClass = $this->getFilterClass(); + + $di = new \RecursiveDirectoryIterator($path, (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)); + $filter = new $filterClass($di, $path, $config, $ruleset); + $iterator = new \RecursiveIteratorIterator($filter); + + foreach ($iterator as $file) { + $this->files[$file->getPathname()] = null; + $this->numFiles++; + } + } else { + $this->addFile($path); + }//end if + }//end foreach + + reset($this->files); + + }//end __construct() + + + /** + * Add a file to the list. + * + * If a file object has already been created, it can be passed here. + * If it is left NULL, it will be created when accessed. + * + * @param string $path The path to the file being added. + * @param \PHP_CodeSniffer\Files\File $file The file being added. + * + * @return void + */ + public function addFile($path, $file=null) + { + // No filtering is done for STDIN when the filename + // has not been specified. + if ($path === 'STDIN') { + $this->files[$path] = $file; + $this->numFiles++; + return; + } + + $filterClass = $this->getFilterClass(); + + $di = new \RecursiveArrayIterator([$path]); + $filter = new $filterClass($di, $path, $this->config, $this->ruleset); + $iterator = new \RecursiveIteratorIterator($filter); + + foreach ($iterator as $path) { + $this->files[$path] = $file; + $this->numFiles++; + } + + }//end addFile() + + + /** + * Get the class name of the filter being used for the run. + * + * @return string + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the specified filter could not be found. + */ + private function getFilterClass() + { + $filterType = $this->config->filter; + + if ($filterType === null) { + $filterClass = '\PHP_CodeSniffer\Filters\Filter'; + } else { + if (strpos($filterType, '.') !== false) { + // This is a path to a custom filter class. + $filename = realpath($filterType); + if ($filename === false) { + $error = "ERROR: Custom filter \"$filterType\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $filterClass = Autoload::loadFile($filename); + } else { + $filterClass = '\PHP_CodeSniffer\Filters\\'.$filterType; + } + } + + return $filterClass; + + }//end getFilterClass() + + + /** + * Rewind the iterator to the first file. + * + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + reset($this->files); + + }//end rewind() + + + /** + * Get the file that is currently being processed. + * + * @return \PHP_CodeSniffer\Files\File + */ + #[ReturnTypeWillChange] + public function current() + { + $path = key($this->files); + if (isset($this->files[$path]) === false) { + $this->files[$path] = new LocalFile($path, $this->ruleset, $this->config); + } + + return $this->files[$path]; + + }//end current() + + + /** + * Return the file path of the current file being processed. + * + * @return void + */ + #[ReturnTypeWillChange] + public function key() + { + return key($this->files); + + }//end key() + + + /** + * Move forward to the next file. + * + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + next($this->files); + + }//end next() + + + /** + * Checks if current position is valid. + * + * @return boolean + */ + #[ReturnTypeWillChange] + public function valid() + { + if (current($this->files) === false) { + return false; + } + + return true; + + }//end valid() + + + /** + * Return the number of files in the list. + * + * @return integer + */ + #[ReturnTypeWillChange] + public function count() + { + return $this->numFiles; + + }//end count() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Files/LocalFile.php b/kirki-composer/squizlabs/php_codesniffer/src/Files/LocalFile.php new file mode 100644 index 000000000..ca2e74ad3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Files/LocalFile.php @@ -0,0 +1,219 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Util\Cache; +use PHP_CodeSniffer\Util\Common; + +class LocalFile extends File +{ + + + /** + * Creates a LocalFile object and sets the content. + * + * @param string $path The absolute path to the file. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($path, Ruleset $ruleset, Config $config) + { + $this->path = trim($path); + if (Common::isReadable($this->path) === false) { + parent::__construct($this->path, $ruleset, $config); + $error = 'Error opening file; file no longer exists or you do not have access to read the file'; + $this->addMessage(true, $error, 1, 1, 'Internal.LocalFile', [], 5, false); + $this->ignored = true; + return; + } + + // Before we go and spend time tokenizing this file, just check + // to see if there is a tag up top to indicate that the whole + // file should be ignored. It must be on one of the first two lines. + if ($config->annotations === true) { + $handle = fopen($this->path, 'r'); + if ($handle !== false) { + $firstContent = fgets($handle); + $firstContent .= fgets($handle); + fclose($handle); + + if (strpos($firstContent, '@codingStandardsIgnoreFile') !== false + || stripos($firstContent, 'phpcs:ignorefile') !== false + ) { + // We are ignoring the whole file. + $this->ignored = true; + return; + } + } + } + + $this->reloadContent(); + + parent::__construct($this->path, $ruleset, $config); + + }//end __construct() + + + /** + * Loads the latest version of the file's content from the file system. + * + * @return void + */ + public function reloadContent() + { + $this->setContent(file_get_contents($this->path)); + + }//end reloadContent() + + + /** + * Processes the file. + * + * @return void + */ + public function process() + { + if ($this->ignored === true) { + return; + } + + if ($this->configCache['cache'] === false) { + parent::process(); + return; + } + + $hash = md5_file($this->path); + $hash .= fileperms($this->path); + $cache = Cache::get($this->path); + if ($cache !== false && $cache['hash'] === $hash) { + // We can't filter metrics, so just load all of them. + $this->metrics = $cache['metrics']; + + if ($this->configCache['recordErrors'] === true) { + // Replay the cached errors and warnings to filter out the ones + // we don't need for this specific run. + $this->configCache['cache'] = false; + $this->replayErrors($cache['errors'], $cache['warnings']); + $this->configCache['cache'] = true; + } else { + $this->errorCount = $cache['errorCount']; + $this->warningCount = $cache['warningCount']; + $this->fixableCount = $cache['fixableCount']; + } + + if (PHP_CODESNIFFER_VERBOSITY > 0 + || (PHP_CODESNIFFER_CBF === true && empty($this->config->files) === false) + ) { + echo "[loaded from cache]... "; + } + + $this->numTokens = $cache['numTokens']; + $this->fromCache = true; + return; + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + + parent::process(); + + $cache = [ + 'hash' => $hash, + 'errors' => $this->errors, + 'warnings' => $this->warnings, + 'metrics' => $this->metrics, + 'errorCount' => $this->errorCount, + 'warningCount' => $this->warningCount, + 'fixableCount' => $this->fixableCount, + 'numTokens' => $this->numTokens, + ]; + + Cache::set($this->path, $cache); + + // During caching, we don't filter out errors in any way, so + // we need to do that manually now by replaying them. + if ($this->configCache['recordErrors'] === true) { + $this->configCache['cache'] = false; + $this->replayErrors($this->errors, $this->warnings); + $this->configCache['cache'] = true; + } + + }//end process() + + + /** + * Clears and replays error and warnings for the file. + * + * Replaying errors and warnings allows for filtering rules to be changed + * and then errors and warnings to be reapplied with the new rules. This is + * particularly useful while caching. + * + * @param array $errors The list of errors to replay. + * @param array $warnings The list of warnings to replay. + * + * @return void + */ + private function replayErrors($errors, $warnings) + { + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + + $this->replayingErrors = true; + + foreach ($errors as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $this->activeListener = $error['listener']; + $this->addMessage( + true, + $error['message'], + $line, + $column, + $error['source'], + [], + $error['severity'], + $error['fixable'] + ); + } + } + } + + foreach ($warnings as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $this->activeListener = $error['listener']; + $this->addMessage( + false, + $error['message'], + $line, + $column, + $error['source'], + [], + $error['severity'], + $error['fixable'] + ); + } + } + } + + $this->replayingErrors = false; + + }//end replayErrors() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Filters/ExactMatch.php b/kirki-composer/squizlabs/php_codesniffer/src/Filters/ExactMatch.php new file mode 100644 index 000000000..13af8ff22 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Filters/ExactMatch.php @@ -0,0 +1,108 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; + +abstract class ExactMatch extends Filter +{ + + /** + * A list of files to exclude. + * + * @var array + */ + private $blacklist = null; + + /** + * A list of files to include. + * + * If the whitelist is empty, only files in the blacklist will be excluded. + * + * @var array + */ + private $whitelist = null; + + + /** + * Check whether the current element of the iterator is acceptable. + * + * If a file is both blacklisted and whitelisted, it will be deemed unacceptable. + * + * @return bool + */ + public function accept() + { + if (parent::accept() === false) { + return false; + } + + if ($this->blacklist === null) { + $this->blacklist = $this->getblacklist(); + } + + if ($this->whitelist === null) { + $this->whitelist = $this->getwhitelist(); + } + + $filePath = Util\Common::realpath($this->current()); + + // If file is both blacklisted and whitelisted, the blacklist takes precedence. + if (isset($this->blacklist[$filePath]) === true) { + return false; + } + + if (empty($this->whitelist) === true && empty($this->blacklist) === false) { + // We are only checking a blacklist, so everything else should be whitelisted. + return true; + } + + return isset($this->whitelist[$filePath]); + + }//end accept() + + + /** + * Returns an iterator for the current entry. + * + * Ensures that the blacklist and whitelist are preserved so they don't have + * to be generated each time. + * + * @return \RecursiveIterator + */ + public function getChildren() + { + $children = parent::getChildren(); + $children->blacklist = $this->blacklist; + $children->whitelist = $this->whitelist; + return $children; + + }//end getChildren() + + + /** + * Get a list of blacklisted file paths. + * + * @return array + */ + abstract protected function getBlacklist(); + + + /** + * Get a list of whitelisted file paths. + * + * @return array + */ + abstract protected function getWhitelist(); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Filters/Filter.php b/kirki-composer/squizlabs/php_codesniffer/src/Filters/Filter.php new file mode 100644 index 000000000..a1246a2c5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Filters/Filter.php @@ -0,0 +1,285 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Config; +use ReturnTypeWillChange; + +class Filter extends \RecursiveFilterIterator +{ + + /** + * The top-level path we are filtering. + * + * @var string + */ + protected $basedir = null; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + protected $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset = null; + + /** + * A list of ignore patterns that apply to directories only. + * + * @var array + */ + protected $ignoreDirPatterns = null; + + /** + * A list of ignore patterns that apply to files only. + * + * @var array + */ + protected $ignoreFilePatterns = null; + + /** + * A list of file paths we've already accepted. + * + * Used to ensure we aren't following circular symlinks. + * + * @var array + */ + protected $acceptedPaths = []; + + + /** + * Constructs a filter. + * + * @param \RecursiveIterator $iterator The iterator we are using to get file paths. + * @param string $basedir The top-level path we are filtering. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @return void + */ + public function __construct($iterator, $basedir, Config $config, Ruleset $ruleset) + { + parent::__construct($iterator); + $this->basedir = $basedir; + $this->config = $config; + $this->ruleset = $ruleset; + + }//end __construct() + + + /** + * Check whether the current element of the iterator is acceptable. + * + * Files are checked for allowed extensions and ignore patterns. + * Directories are checked for ignore patterns only. + * + * @return bool + */ + #[ReturnTypeWillChange] + public function accept() + { + $filePath = $this->current(); + $realPath = Util\Common::realpath($filePath); + + if ($realPath !== false) { + // It's a real path somewhere, so record it + // to check for circular symlinks. + if (isset($this->acceptedPaths[$realPath]) === true) { + // We've been here before. + return false; + } + } + + $filePath = $this->current(); + if (is_dir($filePath) === true) { + if ($this->config->local === true) { + return false; + } + } else if ($this->shouldProcessFile($filePath) === false) { + return false; + } + + if ($this->shouldIgnorePath($filePath) === true) { + return false; + } + + $this->acceptedPaths[$realPath] = true; + return true; + + }//end accept() + + + /** + * Returns an iterator for the current entry. + * + * Ensures that the ignore patterns are preserved so they don't have + * to be generated each time. + * + * @return \RecursiveIterator + */ + #[ReturnTypeWillChange] + public function getChildren() + { + $filterClass = get_called_class(); + $children = new $filterClass( + new \RecursiveDirectoryIterator($this->current(), (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)), + $this->basedir, + $this->config, + $this->ruleset + ); + + // Set the ignore patterns so we don't have to generate them again. + $children->ignoreDirPatterns = $this->ignoreDirPatterns; + $children->ignoreFilePatterns = $this->ignoreFilePatterns; + $children->acceptedPaths = $this->acceptedPaths; + return $children; + + }//end getChildren() + + + /** + * Checks filtering rules to see if a file should be checked. + * + * Checks both file extension filters and path ignore filters. + * + * @param string $path The path to the file being checked. + * + * @return bool + */ + protected function shouldProcessFile($path) + { + // Check that the file's extension is one we are checking. + // We are strict about checking the extension and we don't + // let files through with no extension or that start with a dot. + $fileName = basename($path); + $fileParts = explode('.', $fileName); + if ($fileParts[0] === $fileName || $fileParts[0] === '') { + return false; + } + + // Checking multi-part file extensions, so need to create a + // complete extension list and make sure one is allowed. + $extensions = []; + array_shift($fileParts); + foreach ($fileParts as $part) { + $extensions[implode('.', $fileParts)] = 1; + array_shift($fileParts); + } + + $matches = array_intersect_key($extensions, $this->config->extensions); + if (empty($matches) === true) { + return false; + } + + return true; + + }//end shouldProcessFile() + + + /** + * Checks filtering rules to see if a path should be ignored. + * + * @param string $path The path to the file or directory being checked. + * + * @return bool + */ + protected function shouldIgnorePath($path) + { + if ($this->ignoreFilePatterns === null) { + $this->ignoreDirPatterns = []; + $this->ignoreFilePatterns = []; + + $ignorePatterns = $this->config->ignored; + $rulesetIgnorePatterns = $this->ruleset->getIgnorePatterns(); + foreach ($rulesetIgnorePatterns as $pattern => $type) { + // Ignore standard/sniff specific exclude rules. + if (is_array($type) === true) { + continue; + } + + $ignorePatterns[$pattern] = $type; + } + + foreach ($ignorePatterns as $pattern => $type) { + // If the ignore pattern ends with /* then it is ignoring an entire directory. + if (substr($pattern, -2) === '/*') { + // Need to check this pattern for dirs as well as individual file paths. + $this->ignoreFilePatterns[$pattern] = $type; + + $pattern = substr($pattern, 0, -2).'(?=/|$)'; + $this->ignoreDirPatterns[$pattern] = $type; + } else { + // This is a file-specific pattern, so only need to check this + // for individual file paths. + $this->ignoreFilePatterns[$pattern] = $type; + } + } + }//end if + + $relativePath = $path; + if (strpos($path, $this->basedir) === 0) { + // The +1 cuts off the directory separator as well. + $relativePath = substr($path, (strlen($this->basedir) + 1)); + } + + if (is_dir($path) === true) { + $ignorePatterns = $this->ignoreDirPatterns; + } else { + $ignorePatterns = $this->ignoreFilePatterns; + } + + foreach ($ignorePatterns as $pattern => $type) { + // Maintains backwards compatibility in case the ignore pattern does + // not have a relative/absolute value. + if (is_int($pattern) === true) { + $pattern = $type; + $type = 'absolute'; + } + + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $replacements['/'] = '\\\\'; + } + + $pattern = strtr($pattern, $replacements); + + if ($type === 'relative') { + $testPath = $relativePath; + } else { + $testPath = $path; + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $testPath) === 1) { + return true; + } + }//end foreach + + return false; + + }//end shouldIgnorePath() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Filters/GitModified.php b/kirki-composer/squizlabs/php_codesniffer/src/Filters/GitModified.php new file mode 100644 index 000000000..4b6ef3fc5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Filters/GitModified.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; + +class GitModified extends ExactMatch +{ + + + /** + * Get a list of blacklisted file paths. + * + * @return array + */ + protected function getBlacklist() + { + return []; + + }//end getBlacklist() + + + /** + * Get a list of whitelisted file paths. + * + * @return array + */ + protected function getWhitelist() + { + $modified = []; + + $cmd = 'git ls-files -o -m --exclude-standard -- '.escapeshellarg($this->basedir); + $output = []; + exec($cmd, $output); + + $basedir = $this->basedir; + if (is_dir($basedir) === false) { + $basedir = dirname($basedir); + } + + foreach ($output as $path) { + $path = Util\Common::realpath($path); + + if ($path === false) { + continue; + } + + do { + $modified[$path] = true; + $path = dirname($path); + } while ($path !== $basedir); + } + + return $modified; + + }//end getWhitelist() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Filters/GitStaged.php b/kirki-composer/squizlabs/php_codesniffer/src/Filters/GitStaged.php new file mode 100644 index 000000000..fcb92c3d9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Filters/GitStaged.php @@ -0,0 +1,68 @@ + + * @copyright 2018 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util; + +class GitStaged extends ExactMatch +{ + + + /** + * Get a list of blacklisted file paths. + * + * @return array + */ + protected function getBlacklist() + { + return []; + + }//end getBlacklist() + + + /** + * Get a list of whitelisted file paths. + * + * @return array + */ + protected function getWhitelist() + { + $modified = []; + + $cmd = 'git diff --cached --name-only -- '.escapeshellarg($this->basedir); + $output = []; + exec($cmd, $output); + + $basedir = $this->basedir; + if (is_dir($basedir) === false) { + $basedir = dirname($basedir); + } + + foreach ($output as $path) { + $path = Util\Common::realpath($path); + if ($path === false) { + // Skip deleted files. + continue; + } + + do { + $modified[$path] = true; + $path = dirname($path); + } while ($path !== $basedir); + } + + return $modified; + + }//end getWhitelist() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Fixer.php b/kirki-composer/squizlabs/php_codesniffer/src/Fixer.php new file mode 100644 index 000000000..b8dc05b16 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Fixer.php @@ -0,0 +1,806 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; + +class Fixer +{ + + /** + * Is the fixer enabled and fixing a file? + * + * Sniffs should check this value to ensure they are not + * doing extra processing to prepare for a fix when fixing is + * not required. + * + * @var boolean + */ + public $enabled = false; + + /** + * The number of times we have looped over a file. + * + * @var integer + */ + public $loops = 0; + + /** + * The file being fixed. + * + * @var \PHP_CodeSniffer\Files\File + */ + private $currentFile = null; + + /** + * The list of tokens that make up the file contents. + * + * This is a simplified list which just contains the token content and nothing + * else. This is the array that is updated as fixes are made, not the file's + * token array. Imploding this array will give you the file content back. + * + * @var array + */ + private $tokens = []; + + /** + * A list of tokens that have already been fixed. + * + * We don't allow the same token to be fixed more than once each time + * through a file as this can easily cause conflicts between sniffs. + * + * @var int[] + */ + private $fixedTokens = []; + + /** + * The last value of each fixed token. + * + * If a token is being "fixed" back to its last value, the fix is + * probably conflicting with another. + * + * @var array + */ + private $oldTokenValues = []; + + /** + * A list of tokens that have been fixed during a changeset. + * + * All changes in changeset must be able to be applied, or else + * the entire changeset is rejected. + * + * @var array + */ + private $changeset = []; + + /** + * Is there an open changeset. + * + * @var boolean + */ + private $inChangeset = false; + + /** + * Is the current fixing loop in conflict? + * + * @var boolean + */ + private $inConflict = false; + + /** + * The number of fixes that have been performed. + * + * @var integer + */ + private $numFixes = 0; + + + /** + * Starts fixing a new file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being fixed. + * + * @return void + */ + public function startFile(File $phpcsFile) + { + $this->currentFile = $phpcsFile; + $this->numFixes = 0; + $this->fixedTokens = []; + + $tokens = $phpcsFile->getTokens(); + $this->tokens = []; + foreach ($tokens as $index => $token) { + if (isset($token['orig_content']) === true) { + $this->tokens[$index] = $token['orig_content']; + } else { + $this->tokens[$index] = $token['content']; + } + } + + }//end startFile() + + + /** + * Attempt to fix the file by processing it until no fixes are made. + * + * @return boolean + */ + public function fixFile() + { + $fixable = $this->currentFile->getFixableCount(); + if ($fixable === 0) { + // Nothing to fix. + return false; + } + + $this->enabled = true; + + $this->loops = 0; + while ($this->loops < 50) { + ob_start(); + + // Only needed once file content has changed. + $contents = $this->getContents(); + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + @ob_end_clean(); + echo '---START FILE CONTENT---'.PHP_EOL; + $lines = explode($this->currentFile->eolChar, $contents); + $max = strlen(count($lines)); + foreach ($lines as $lineNum => $line) { + $lineNum++; + echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL; + } + + echo '--- END FILE CONTENT ---'.PHP_EOL; + ob_start(); + } + + $this->inConflict = false; + $this->currentFile->ruleset->populateTokenListeners(); + $this->currentFile->setContent($contents); + $this->currentFile->process(); + ob_end_clean(); + + $this->loops++; + + if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) { + echo "\r".str_repeat(' ', 80)."\r"; + echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass"; + if ($this->loops > 1) { + echo 'es'; + } + + echo ']... '; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + if ($this->numFixes === 0 && $this->inConflict === false) { + // Nothing left to do. + break; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL; + } + }//end while + + $this->enabled = false; + + if ($this->numFixes > 0) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if (ob_get_level() > 0) { + ob_end_clean(); + } + + echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL; + ob_start(); + } + + return false; + } + + return true; + + }//end fixFile() + + + /** + * Generates a text diff of the original file and the new content. + * + * @param string $filePath Optional file path to diff the file against. + * If not specified, the original version of the + * file will be used. + * @param boolean $colors Print coloured output or not. + * + * @return string + */ + public function generateDiff($filePath=null, $colors=true) + { + if ($filePath === null) { + $filePath = $this->currentFile->getFilename(); + } + + $cwd = getcwd().DIRECTORY_SEPARATOR; + if (strpos($filePath, $cwd) === 0) { + $filename = substr($filePath, strlen($cwd)); + } else { + $filename = $filePath; + } + + $contents = $this->getContents(); + + $tempName = tempnam(sys_get_temp_dir(), 'phpcs-fixer'); + $fixedFile = fopen($tempName, 'w'); + fwrite($fixedFile, $contents); + + // We must use something like shell_exec() because whitespace at the end + // of lines is critical to diff files. + $filename = escapeshellarg($filename); + $cmd = "diff -u -L$filename -LPHP_CodeSniffer $filename \"$tempName\""; + + $diff = shell_exec($cmd); + + fclose($fixedFile); + if (is_file($tempName) === true) { + unlink($tempName); + } + + if ($diff === null) { + return ''; + } + + if ($colors === false) { + return $diff; + } + + $diffLines = explode(PHP_EOL, $diff); + if (count($diffLines) === 1) { + // Seems to be required for cygwin. + $diffLines = explode("\n", $diff); + } + + $diff = []; + foreach ($diffLines as $line) { + if (isset($line[0]) === true) { + switch ($line[0]) { + case '-': + $diff[] = "\033[31m$line\033[0m"; + break; + case '+': + $diff[] = "\033[32m$line\033[0m"; + break; + default: + $diff[] = $line; + } + } + } + + $diff = implode(PHP_EOL, $diff); + + return $diff; + + }//end generateDiff() + + + /** + * Get a count of fixes that have been performed on the file. + * + * This value is reset every time a new file is started, or an existing + * file is restarted. + * + * @return int + */ + public function getFixCount() + { + return $this->numFixes; + + }//end getFixCount() + + + /** + * Get the current content of the file, as a string. + * + * @return string + */ + public function getContents() + { + $contents = implode($this->tokens); + return $contents; + + }//end getContents() + + + /** + * Get the current fixed content of a token. + * + * This function takes changesets into account so should be used + * instead of directly accessing the token array. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return string + */ + public function getTokenContent($stackPtr) + { + if ($this->inChangeset === true + && isset($this->changeset[$stackPtr]) === true + ) { + return $this->changeset[$stackPtr]; + } else { + return $this->tokens[$stackPtr]; + } + + }//end getTokenContent() + + + /** + * Start recording actions for a changeset. + * + * @return void + */ + public function beginChangeset() + { + if ($this->inConflict === true) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === __CLASS__) { + $sniff = 'Fixer'; + } else { + $sniff = Util\Common::getSniffCode($bt[1]['class']); + } + + $line = $bt[0]['line']; + + @ob_end_clean(); + echo "\t=> Changeset started by $sniff:$line".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + $this->inChangeset = true; + + }//end beginChangeset() + + + /** + * Stop recording actions for a changeset, and apply logged changes. + * + * @return boolean + */ + public function endChangeset() + { + if ($this->inConflict === true) { + return false; + } + + $this->inChangeset = false; + + $success = true; + $applied = []; + foreach ($this->changeset as $stackPtr => $content) { + $success = $this->replaceToken($stackPtr, $content); + if ($success === false) { + break; + } else { + $applied[] = $stackPtr; + } + } + + if ($success === false) { + // Rolling back all changes. + foreach ($applied as $stackPtr) { + $this->revertToken($stackPtr); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "\t=> Changeset failed to apply".PHP_EOL; + ob_start(); + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + $fixes = count($this->changeset); + @ob_end_clean(); + echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + return true; + + }//end endChangeset() + + + /** + * Stop recording actions for a changeset, and discard logged changes. + * + * @return void + */ + public function rollbackChangeset() + { + $this->inChangeset = false; + $this->inConflict = false; + + if (empty($this->changeset) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Util\Common::getSniffCode($sniff); + + $numChanges = count($this->changeset); + + @ob_end_clean(); + echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL; + echo "\t=> Changeset rolled back".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + }//end if + + }//end rollbackChangeset() + + + /** + * Replace the entire contents of a token. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The new content of the token. + * + * @return bool If the change was accepted. + */ + public function replaceToken($stackPtr, $content) + { + if ($this->inConflict === true) { + return false; + } + + if ($this->inChangeset === false + && isset($this->fixedTokens[$stackPtr]) === true + ) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\t"; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL; + ob_start(); + } + + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Util\Common::getSniffCode($sniff); + + $tokens = $this->currentFile->getTokens(); + $type = $tokens[$stackPtr]['type']; + $tokenLine = $tokens[$stackPtr]['line']; + $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]); + $newContent = Common::prepareForOutput($content); + if (trim($this->tokens[$stackPtr]) === '' && isset($this->tokens[($stackPtr + 1)]) === true) { + // Add some context for whitespace only changes. + $append = Common::prepareForOutput($this->tokens[($stackPtr + 1)]); + $oldContent .= $append; + $newContent .= $append; + } + }//end if + + if ($this->inChangeset === true) { + $this->changeset[$stackPtr] = $content; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + } + + if (isset($this->oldTokenValues[$stackPtr]) === false) { + $this->oldTokenValues[$stackPtr] = [ + 'curr' => $content, + 'prev' => $this->tokens[$stackPtr], + 'loop' => $this->loops, + ]; + } else { + if ($this->oldTokenValues[$stackPtr]['prev'] === $content + && $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\t"; + } + + $loop = $this->oldTokenValues[$stackPtr]['loop']; + + @ob_end_clean(); + echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL; + echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL; + } + + if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) { + $this->inConflict = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "$indent**** ignoring all changes until next loop ****".PHP_EOL; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + ob_start(); + } + + return false; + }//end if + + $this->oldTokenValues[$stackPtr]['prev'] = $this->oldTokenValues[$stackPtr]['curr']; + $this->oldTokenValues[$stackPtr]['curr'] = $content; + $this->oldTokenValues[$stackPtr]['loop'] = $this->loops; + }//end if + + $this->fixedTokens[$stackPtr] = $this->tokens[$stackPtr]; + $this->tokens[$stackPtr] = $content; + $this->numFixes++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\tA: "; + } + + if (ob_get_level() > 0) { + ob_end_clean(); + } + + echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + + }//end replaceToken() + + + /** + * Reverts the previous fix made to a token. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If a change was reverted. + */ + public function revertToken($stackPtr) + { + if (isset($this->fixedTokens[$stackPtr]) === false) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Util\Common::getSniffCode($sniff); + + $tokens = $this->currentFile->getTokens(); + $type = $tokens[$stackPtr]['type']; + $tokenLine = $tokens[$stackPtr]['line']; + $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]); + $newContent = Common::prepareForOutput($this->fixedTokens[$stackPtr]); + if (trim($this->tokens[$stackPtr]) === '' && isset($tokens[($stackPtr + 1)]) === true) { + // Add some context for whitespace only changes. + $append = Common::prepareForOutput($this->tokens[($stackPtr + 1)]); + $oldContent .= $append; + $newContent .= $append; + } + }//end if + + $this->tokens[$stackPtr] = $this->fixedTokens[$stackPtr]; + unset($this->fixedTokens[$stackPtr]); + $this->numFixes--; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\tR: "; + } + + @ob_end_clean(); + echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + + }//end revertToken() + + + /** + * Replace the content of a token with a part of its current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param int $start The first character to keep. + * @param int $length The number of characters to keep. If NULL, the content of + * the token from $start to the end of the content is kept. + * + * @return bool If the change was accepted. + */ + public function substrToken($stackPtr, $start, $length=null) + { + $current = $this->getTokenContent($stackPtr); + + if ($length === null) { + $newContent = substr($current, $start); + } else { + $newContent = substr($current, $start, $length); + } + + return $this->replaceToken($stackPtr, $newContent); + + }//end substrToken() + + + /** + * Adds a newline to end of a token's content. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If the change was accepted. + */ + public function addNewline($stackPtr) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $current.$this->currentFile->eolChar); + + }//end addNewline() + + + /** + * Adds a newline to the start of a token's content. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If the change was accepted. + */ + public function addNewlineBefore($stackPtr) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $this->currentFile->eolChar.$current); + + }//end addNewlineBefore() + + + /** + * Adds content to the end of a token's current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The content to add. + * + * @return bool If the change was accepted. + */ + public function addContent($stackPtr, $content) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $current.$content); + + }//end addContent() + + + /** + * Adds content to the start of a token's current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The content to add. + * + * @return bool If the change was accepted. + */ + public function addContentBefore($stackPtr, $content) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $content.$current); + + }//end addContentBefore() + + + /** + * Adjust the indent of a code block. + * + * @param int $start The position of the token in the token stack + * to start adjusting the indent from. + * @param int $end The position of the token in the token stack + * to end adjusting the indent. + * @param int $change The number of spaces to adjust the indent by + * (positive or negative). + * + * @return void + */ + public function changeCodeBlockIndent($start, $end, $change) + { + $tokens = $this->currentFile->getTokens(); + + $baseIndent = ''; + if ($change > 0) { + $baseIndent = str_repeat(' ', $change); + } + + $useChangeset = false; + if ($this->inChangeset === false) { + $this->beginChangeset(); + $useChangeset = true; + } + + for ($i = $start; $i <= $end; $i++) { + if ($tokens[$i]['column'] !== 1 + || $tokens[($i + 1)]['line'] !== $tokens[$i]['line'] + ) { + continue; + } + + $length = 0; + if ($tokens[$i]['code'] === T_WHITESPACE + || $tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $length = $tokens[$i]['length']; + + $padding = ($length + $change); + if ($padding > 0) { + $padding = str_repeat(' ', $padding); + } else { + $padding = ''; + } + + $newContent = $padding.ltrim($tokens[$i]['content']); + } else { + $newContent = $baseIndent.$tokens[$i]['content']; + } + + $this->replaceToken($i, $newContent); + }//end for + + if ($useChangeset === true) { + $this->endChangeset(); + } + + }//end changeCodeBlockIndent() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Generators/Generator.php b/kirki-composer/squizlabs/php_codesniffer/src/Generators/Generator.php new file mode 100644 index 000000000..56049768b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Generators/Generator.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Autoload; + +abstract class Generator +{ + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * XML documentation files used to produce the final output. + * + * @var string[] + */ + public $docFiles = []; + + + /** + * Constructs a doc generator. + * + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @see generate() + */ + public function __construct(Ruleset $ruleset) + { + $this->ruleset = $ruleset; + + foreach ($ruleset->sniffs as $className => $sniffClass) { + $file = Autoload::getLoadedFileName($className); + $docFile = str_replace( + DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR, + DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR, + $file + ); + $docFile = str_replace('Sniff.php', 'Standard.xml', $docFile); + + if (is_file($docFile) === true) { + $this->docFiles[] = $docFile; + } + } + + }//end __construct() + + + /** + * Retrieves the title of the sniff from the DOMNode supplied. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return string + */ + protected function getTitle(\DOMNode $doc) + { + return $doc->getAttribute('title'); + + }//end getTitle() + + + /** + * Generates the documentation for a standard. + * + * It's probably wise for doc generators to override this method so they + * have control over how the docs are produced. Otherwise, the processSniff + * method should be overridden to output content for each sniff. + * + * @return void + * @see processSniff() + */ + public function generate() + { + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + }//end generate() + + + /** + * Process the documentation for a single sniff. + * + * Doc generators must implement this function to produce output. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + * @see generate() + */ + abstract protected function processSniff(\DOMNode $doc); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Generators/HTML.php b/kirki-composer/squizlabs/php_codesniffer/src/Generators/HTML.php new file mode 100644 index 000000000..db2646843 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Generators/HTML.php @@ -0,0 +1,270 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use PHP_CodeSniffer\Config; + +class HTML extends Generator +{ + + + /** + * Generates the documentation for a standard. + * + * @return void + * @see processSniff() + */ + public function generate() + { + ob_start(); + $this->printHeader(); + $this->printToc(); + + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + $this->printFooter(); + + $content = ob_get_contents(); + ob_end_clean(); + + echo $content; + + }//end generate() + + + /** + * Print the header of the HTML page. + * + * @return void + */ + protected function printHeader() + { + $standard = $this->ruleset->name; + echo ''.PHP_EOL; + echo ' '.PHP_EOL; + echo " $standard Coding Standards".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo "

$standard Coding Standards

".PHP_EOL; + + }//end printHeader() + + + /** + * Print the table of contents for the standard. + * + * The TOC is just an unordered list of bookmarks to sniffs on the page. + * + * @return void + */ + protected function printToc() + { + echo '

Table of Contents

'.PHP_EOL; + echo '
    '.PHP_EOL; + + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $title = $this->getTitle($documentation); + echo '
  • $title
  • ".PHP_EOL; + } + + echo '
'.PHP_EOL; + + }//end printToc() + + + /** + * Print the footer of the HTML page. + * + * @return void + */ + protected function printFooter() + { + // Turn off errors so we don't get timezone warnings if people + // don't have their timezone set. + $errorLevel = error_reporting(0); + echo '
'; + echo 'Documentation generated on '.date('r'); + echo ' by PHP_CodeSniffer '.Config::VERSION.''; + echo '
'.PHP_EOL; + error_reporting($errorLevel); + + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + + }//end printFooter() + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + public function processSniff(\DOMNode $doc) + { + $title = $this->getTitle($doc); + echo ' '.PHP_EOL; + echo "

$title

".PHP_EOL; + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(\DOMNode $node) + { + $content = trim($node->nodeValue); + $content = htmlspecialchars($content); + + // Allow em tags only. + $content = str_replace('<em>', '', $content); + $content = str_replace('</em>', '', $content); + + echo "

$content

".PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(\DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + $first = trim($codeBlocks->item(0)->nodeValue); + $first = str_replace('', $first); + $first = str_replace(' ', ' ', $first); + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + $second = trim($codeBlocks->item(1)->nodeValue); + $second = str_replace('', $second); + $second = str_replace(' ', ' ', $second); + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo '
$firstTitle$secondTitle
$first$second
'.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Generators/Markdown.php b/kirki-composer/squizlabs/php_codesniffer/src/Generators/Markdown.php new file mode 100644 index 000000000..9756bcf14 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Generators/Markdown.php @@ -0,0 +1,161 @@ + + * @copyright 2014 Arroba IT + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use PHP_CodeSniffer\Config; + +class Markdown extends Generator +{ + + + /** + * Generates the documentation for a standard. + * + * @return void + * @see processSniff() + */ + public function generate() + { + ob_start(); + $this->printHeader(); + + foreach ($this->docFiles as $file) { + $doc = new \DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + $this->printFooter(); + $content = ob_get_contents(); + ob_end_clean(); + + echo $content; + + }//end generate() + + + /** + * Print the markdown header. + * + * @return void + */ + protected function printHeader() + { + $standard = $this->ruleset->name; + + echo "# $standard Coding Standard".PHP_EOL; + + }//end printHeader() + + + /** + * Print the markdown footer. + * + * @return void + */ + protected function printFooter() + { + // Turn off errors so we don't get timezone warnings if people + // don't have their timezone set. + error_reporting(0); + echo 'Documentation generated on '.date('r'); + echo ' by [PHP_CodeSniffer '.Config::VERSION.'](https://github.com/squizlabs/PHP_CodeSniffer)'.PHP_EOL; + + }//end printFooter() + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + protected function processSniff(\DOMNode $doc) + { + $title = $this->getTitle($doc); + echo PHP_EOL."## $title".PHP_EOL; + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(\DOMNode $node) + { + $content = trim($node->nodeValue); + $content = htmlspecialchars($content); + + $content = str_replace('<em>', '*', $content); + $content = str_replace('</em>', '*', $content); + + echo $content.PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(\DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + $first = trim($codeBlocks->item(0)->nodeValue); + $first = str_replace("\n", "\n ", $first); + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + $second = trim($codeBlocks->item(1)->nodeValue); + $second = str_replace("\n", "\n ", $second); + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo ' '.PHP_EOL; + echo '
$firstTitle$secondTitle
'.PHP_EOL.PHP_EOL; + echo " $first".PHP_EOL.PHP_EOL; + echo ''.PHP_EOL.PHP_EOL; + echo " $second".PHP_EOL.PHP_EOL; + echo '
'.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Generators/Text.php b/kirki-composer/squizlabs/php_codesniffer/src/Generators/Text.php new file mode 100644 index 000000000..ffff206aa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Generators/Text.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +class Text extends Generator +{ + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + public function processSniff(\DOMNode $doc) + { + $this->printTitle($doc); + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Prints the title area for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + protected function printTitle(\DOMNode $doc) + { + $title = $this->getTitle($doc); + $standard = $this->ruleset->name; + + echo PHP_EOL; + echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4)); + echo strtoupper(PHP_EOL."| $standard CODING STANDARD: $title |".PHP_EOL); + echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4)); + echo PHP_EOL.PHP_EOL; + + }//end printTitle() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(\DOMNode $node) + { + $text = trim($node->nodeValue); + $text = str_replace('', '*', $text); + $text = str_replace('', '*', $text); + + $nodeLines = explode("\n", $text); + $lines = []; + + foreach ($nodeLines as $currentLine) { + $currentLine = trim($currentLine); + if ($currentLine === '') { + // The text contained a blank line. Respect this. + $lines[] = ''; + continue; + } + + $tempLine = ''; + $words = explode(' ', $currentLine); + + foreach ($words as $word) { + $currentLength = strlen($tempLine.$word); + if ($currentLength < 99) { + $tempLine .= $word.' '; + continue; + } + + if ($currentLength === 99 || $currentLength === 100) { + // We are already at the edge, so we are done. + $lines[] = $tempLine.$word; + $tempLine = ''; + } else { + $lines[] = rtrim($tempLine); + $tempLine = $word.' '; + } + }//end foreach + + if ($tempLine !== '') { + $lines[] = rtrim($tempLine); + } + }//end foreach + + echo implode(PHP_EOL, $lines).PHP_EOL.PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(\DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + $first = trim($codeBlocks->item(0)->nodeValue); + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + + $firstTitleLines = []; + $tempTitle = ''; + $words = explode(' ', $firstTitle); + + foreach ($words as $word) { + if (strlen($tempTitle.$word) >= 45) { + if (strlen($tempTitle.$word) === 45) { + // Adding the extra space will push us to the edge + // so we are done. + $firstTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else if (strlen($tempTitle.$word) === 46) { + // We are already at the edge, so we are done. + $firstTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else { + $firstTitleLines[] = $tempTitle; + $tempTitle = $word.' '; + } + } else { + $tempTitle .= $word.' '; + } + }//end foreach + + if ($tempTitle !== '') { + $firstTitleLines[] = $tempTitle; + } + + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + $firstLines = explode("\n", $first); + + $second = trim($codeBlocks->item(1)->nodeValue); + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + + $secondTitleLines = []; + $tempTitle = ''; + $words = explode(' ', $secondTitle); + + foreach ($words as $word) { + if (strlen($tempTitle.$word) >= 45) { + if (strlen($tempTitle.$word) === 45) { + // Adding the extra space will push us to the edge + // so we are done. + $secondTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else if (strlen($tempTitle.$word) === 46) { + // We are already at the edge, so we are done. + $secondTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else { + $secondTitleLines[] = $tempTitle; + $tempTitle = $word.' '; + } + } else { + $tempTitle .= $word.' '; + } + }//end foreach + + if ($tempTitle !== '') { + $secondTitleLines[] = $tempTitle; + } + + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + $secondLines = explode("\n", $second); + + $maxCodeLines = max(count($firstLines), count($secondLines)); + $maxTitleLines = max(count($firstTitleLines), count($secondTitleLines)); + + echo str_repeat('-', 41); + echo ' CODE COMPARISON '; + echo str_repeat('-', 42).PHP_EOL; + + for ($i = 0; $i < $maxTitleLines; $i++) { + if (isset($firstTitleLines[$i]) === true) { + $firstLineText = $firstTitleLines[$i]; + } else { + $firstLineText = ''; + } + + if (isset($secondTitleLines[$i]) === true) { + $secondLineText = $secondTitleLines[$i]; + } else { + $secondLineText = ''; + } + + echo '| '; + echo $firstLineText.str_repeat(' ', (46 - strlen($firstLineText))); + echo ' | '; + echo $secondLineText.str_repeat(' ', (47 - strlen($secondLineText))); + echo ' |'.PHP_EOL; + }//end for + + echo str_repeat('-', 100).PHP_EOL; + + for ($i = 0; $i < $maxCodeLines; $i++) { + if (isset($firstLines[$i]) === true) { + $firstLineText = $firstLines[$i]; + } else { + $firstLineText = ''; + } + + if (isset($secondLines[$i]) === true) { + $secondLineText = $secondLines[$i]; + } else { + $secondLineText = ''; + } + + echo '| '; + echo $firstLineText.str_repeat(' ', max(0, (47 - strlen($firstLineText)))); + echo '| '; + echo $secondLineText.str_repeat(' ', max(0, (48 - strlen($secondLineText)))); + echo '|'.PHP_EOL; + }//end for + + echo str_repeat('-', 100).PHP_EOL.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reporter.php b/kirki-composer/squizlabs/php_codesniffer/src/Reporter.php new file mode 100644 index 000000000..e89a20edf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reporter.php @@ -0,0 +1,423 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Reports\Report; +use PHP_CodeSniffer\Util\Common; + +class Reporter +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * Total number of files that contain errors or warnings. + * + * @var integer + */ + public $totalFiles = 0; + + /** + * Total number of errors found during the run. + * + * @var integer + */ + public $totalErrors = 0; + + /** + * Total number of warnings found during the run. + * + * @var integer + */ + public $totalWarnings = 0; + + /** + * Total number of errors/warnings that can be fixed. + * + * @var integer + */ + public $totalFixable = 0; + + /** + * Total number of errors/warnings that were fixed. + * + * @var integer + */ + public $totalFixed = 0; + + /** + * When the PHPCS run started. + * + * @var float + */ + public static $startTime = 0; + + /** + * A cache of report objects. + * + * @var array + */ + private $reports = []; + + /** + * A cache of opened temporary files. + * + * @var array + */ + private $tmpFiles = []; + + + /** + * Initialise the reporter. + * + * All reports specified in the config will be created and their + * output file (or a temp file if none is specified) initialised by + * clearing the current contents. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If a custom report class could not be found. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If a report class is incorrectly set up. + */ + public function __construct(Config $config) + { + $this->config = $config; + + foreach ($config->reports as $type => $output) { + if ($output === null) { + $output = $config->reportFile; + } + + $reportClassName = ''; + if (strpos($type, '.') !== false) { + // This is a path to a custom report class. + $filename = realpath($type); + if ($filename === false) { + $error = "ERROR: Custom report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $reportClassName = Autoload::loadFile($filename); + } else if (class_exists('PHP_CodeSniffer\Reports\\'.ucfirst($type)) === true) { + // PHPCS native report. + $reportClassName = 'PHP_CodeSniffer\Reports\\'.ucfirst($type); + } else if (class_exists($type) === true) { + // FQN of a custom report. + $reportClassName = $type; + } else { + // OK, so not a FQN, try and find the report using the registered namespaces. + $registeredNamespaces = Autoload::getSearchPaths(); + $trimmedType = ltrim($type, '\\'); + + foreach ($registeredNamespaces as $nsPrefix) { + if ($nsPrefix === '') { + continue; + } + + if (class_exists($nsPrefix.'\\'.$trimmedType) === true) { + $reportClassName = $nsPrefix.'\\'.$trimmedType; + break; + } + } + }//end if + + if ($reportClassName === '') { + $error = "ERROR: Class file for report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $reportClass = new $reportClassName(); + if (($reportClass instanceof Report) === false) { + throw new RuntimeException('Class "'.$reportClassName.'" must implement the "PHP_CodeSniffer\Report" interface.'); + } + + $this->reports[$type] = [ + 'output' => $output, + 'class' => $reportClass, + ]; + + if ($output === null) { + // Using a temp file. + // This needs to be set in the constructor so that all + // child procs use the same report file when running in parallel. + $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs'); + file_put_contents($this->tmpFiles[$type], ''); + } else { + file_put_contents($output, ''); + } + }//end foreach + + }//end __construct() + + + /** + * Generates and prints final versions of all reports. + * + * Returns TRUE if any of the reports output content to the screen + * or FALSE if all reports were silently printed to a file. + * + * @return bool + */ + public function printReports() + { + $toScreen = false; + foreach ($this->reports as $type => $report) { + if ($report['output'] === null) { + $toScreen = true; + } + + $this->printReport($type); + } + + return $toScreen; + + }//end printReports() + + + /** + * Generates and prints a single final report. + * + * @param string $report The report type to print. + * + * @return void + */ + public function printReport($report) + { + $reportClass = $this->reports[$report]['class']; + $reportFile = $this->reports[$report]['output']; + + if ($reportFile !== null) { + $filename = $reportFile; + $toScreen = false; + } else { + if (isset($this->tmpFiles[$report]) === true) { + $filename = $this->tmpFiles[$report]; + } else { + $filename = null; + } + + $toScreen = true; + } + + $reportCache = ''; + if ($filename !== null) { + $reportCache = file_get_contents($filename); + } + + ob_start(); + $reportClass->generate( + $reportCache, + $this->totalFiles, + $this->totalErrors, + $this->totalWarnings, + $this->totalFixable, + $this->config->showSources, + $this->config->reportWidth, + $this->config->interactive, + $toScreen + ); + $generatedReport = ob_get_contents(); + ob_end_clean(); + + if ($this->config->colors !== true || $reportFile !== null) { + $generatedReport = preg_replace('`\033\[[0-9;]+m`', '', $generatedReport); + } + + if ($reportFile !== null) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo $generatedReport; + } + + file_put_contents($reportFile, $generatedReport.PHP_EOL); + } else { + echo $generatedReport; + if ($filename !== null && file_exists($filename) === true) { + unlink($filename); + unset($this->tmpFiles[$report]); + } + } + + }//end printReport() + + + /** + * Caches the result of a single processed file for all reports. + * + * The report content that is generated is appended to the output file + * assigned to each report. This content may be an intermediate report format + * and not reflect the final report output. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed. + * + * @return void + */ + public function cacheFileReport(File $phpcsFile) + { + if (isset($this->config->reports) === false) { + // This happens during unit testing, or any time someone just wants + // the error data and not the printed report. + return; + } + + $reportData = $this->prepareFileReport($phpcsFile); + $errorsShown = false; + + foreach ($this->reports as $type => $report) { + $reportClass = $report['class']; + + ob_start(); + $result = $reportClass->generateFileReport($reportData, $phpcsFile, $this->config->showSources, $this->config->reportWidth); + if ($result === true) { + $errorsShown = true; + } + + $generatedReport = ob_get_contents(); + ob_end_clean(); + + if ($report['output'] === null) { + // Using a temp file. + if (isset($this->tmpFiles[$type]) === false) { + // When running in interactive mode, the reporter prints the full + // report many times, which will unlink the temp file. So we need + // to create a new one if it doesn't exist. + $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs'); + file_put_contents($this->tmpFiles[$type], ''); + } + + file_put_contents($this->tmpFiles[$type], $generatedReport, (FILE_APPEND | LOCK_EX)); + } else { + file_put_contents($report['output'], $generatedReport, (FILE_APPEND | LOCK_EX)); + }//end if + }//end foreach + + if ($errorsShown === true || PHP_CODESNIFFER_CBF === true) { + $this->totalFiles++; + $this->totalErrors += $reportData['errors']; + $this->totalWarnings += $reportData['warnings']; + + // When PHPCBF is running, we need to use the fixable error values + // after the report has run and fixed what it can. + if (PHP_CODESNIFFER_CBF === true) { + $this->totalFixable += $phpcsFile->getFixableCount(); + $this->totalFixed += $phpcsFile->getFixedCount(); + } else { + $this->totalFixable += $reportData['fixable']; + } + } + + }//end cacheFileReport() + + + /** + * Generate summary information to be used during report generation. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed. + * + * @return array + */ + public function prepareFileReport(File $phpcsFile) + { + $report = [ + 'filename' => Common::stripBasepath($phpcsFile->getFilename(), $this->config->basepath), + 'errors' => $phpcsFile->getErrorCount(), + 'warnings' => $phpcsFile->getWarningCount(), + 'fixable' => $phpcsFile->getFixableCount(), + 'messages' => [], + ]; + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Prefect score! + return $report; + } + + if ($this->config->recordErrors === false) { + $message = 'Errors are not being recorded but this report requires error messages. '; + $message .= 'This report will not show the correct information.'; + $report['messages'][1][1] = [ + [ + 'message' => $message, + 'source' => 'Internal.RecordErrors', + 'severity' => 5, + 'fixable' => false, + 'type' => 'ERROR', + ], + ]; + return $report; + } + + $errors = []; + + // Merge errors and warnings. + foreach ($phpcsFile->getErrors() as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + $newErrors = []; + foreach ($colErrors as $data) { + $newErrors[] = [ + 'message' => $data['message'], + 'source' => $data['source'], + 'severity' => $data['severity'], + 'fixable' => $data['fixable'], + 'type' => 'ERROR', + ]; + } + + $errors[$line][$column] = $newErrors; + } + + ksort($errors[$line]); + }//end foreach + + foreach ($phpcsFile->getWarnings() as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $colWarnings) { + $newWarnings = []; + foreach ($colWarnings as $data) { + $newWarnings[] = [ + 'message' => $data['message'], + 'source' => $data['source'], + 'severity' => $data['severity'], + 'fixable' => $data['fixable'], + 'type' => 'WARNING', + ]; + } + + if (isset($errors[$line]) === false) { + $errors[$line] = []; + } + + if (isset($errors[$line][$column]) === true) { + $errors[$line][$column] = array_merge( + $newWarnings, + $errors[$line][$column] + ); + } else { + $errors[$line][$column] = $newWarnings; + } + }//end foreach + + ksort($errors[$line]); + }//end foreach + + ksort($errors); + $report['messages'] = $errors; + return $report; + + }//end prepareFileReport() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Cbf.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Cbf.php new file mode 100644 index 000000000..0ecde76e6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Cbf.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Cbf implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $errors = $phpcsFile->getFixableCount(); + if ($errors !== 0) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + ob_end_clean(); + $startTime = microtime(true); + echo "\t=> Fixing file: $errors/$errors violations remaining"; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + $fixed = $phpcsFile->fixer->fixFile(); + } + + if ($phpcsFile->config->stdin === true) { + // Replacing STDIN, so output current file to STDOUT + // even if nothing was fixed. Exit here because we + // can't process any more than 1 file in this setup. + $fixedContent = $phpcsFile->fixer->getContents(); + throw new DeepExitException($fixedContent, 1); + } + + if ($errors === 0) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($fixed === false) { + echo 'ERROR'; + } else { + echo 'DONE'; + } + + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo " in {$timeTaken}ms".PHP_EOL; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo " in $timeTaken secs".PHP_EOL; + } + } + + if ($fixed === true) { + // The filename in the report may be truncated due to a basepath setting + // but we are using it for writing here and not display, + // so find the correct path if basepath is in use. + $newFilename = $report['filename'].$phpcsFile->config->suffix; + if ($phpcsFile->config->basepath !== null) { + $newFilename = $phpcsFile->config->basepath.DIRECTORY_SEPARATOR.$newFilename; + } + + $newContent = $phpcsFile->fixer->getContents(); + file_put_contents($newFilename, $newContent); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($newFilename === $report['filename']) { + echo "\t=> File was overwritten".PHP_EOL; + } else { + echo "\t=> Fixed file written to ".basename($newFilename).PHP_EOL; + } + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + ob_start(); + } + + $errorCount = $phpcsFile->getErrorCount(); + $warningCount = $phpcsFile->getWarningCount(); + $fixableCount = $phpcsFile->getFixableCount(); + $fixedCount = ($errors - $fixableCount); + echo $report['filename'].">>$errorCount>>$warningCount>>$fixableCount>>$fixedCount".PHP_EOL; + + return $fixed; + + }//end generateFileReport() + + + /** + * Prints a summary of fixed files. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + echo PHP_EOL.'No fixable errors were found'.PHP_EOL; + return; + } + + $reportFiles = []; + $maxLength = 0; + $totalFixed = 0; + $failures = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $fileLen = strlen($parts[0]); + $reportFiles[$parts[0]] = [ + 'errors' => $parts[1], + 'warnings' => $parts[2], + 'fixable' => $parts[3], + 'fixed' => $parts[4], + 'strlen' => $fileLen, + ]; + + $maxLength = max($maxLength, $fileLen); + + $totalFixed += $parts[4]; + + if ($parts[3] > 0) { + $failures++; + } + } + + $width = min($width, ($maxLength + 21)); + $width = max($width, 70); + + echo PHP_EOL."\033[1m".'PHPCBF RESULT SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'FILE'.str_repeat(' ', ($width - 20)).'FIXED REMAINING'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + foreach ($reportFiles as $file => $data) { + $padding = ($width - 18 - $data['strlen']); + if ($padding < 0) { + $file = '...'.substr($file, (($padding * -1) + 3)); + $padding = 0; + } + + echo $file.str_repeat(' ', $padding).' '; + + if ($data['fixable'] > 0) { + echo "\033[31mFAILED TO FIX\033[0m".PHP_EOL; + continue; + } + + $remaining = ($data['errors'] + $data['warnings']); + + if ($data['fixed'] !== 0) { + echo $data['fixed']; + echo str_repeat(' ', (7 - strlen((string) $data['fixed']))); + } else { + echo '0 '; + } + + if ($remaining !== 0) { + echo $remaining; + } else { + echo '0'; + } + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1mA TOTAL OF $totalFixed ERROR"; + if ($totalFixed !== 1) { + echo 'S'; + } + + $numFiles = count($reportFiles); + echo ' WERE FIXED IN '.$numFiles.' FILE'; + if ($numFiles !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($failures > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF FAILED TO FIX $failures FILE"; + if ($failures !== 1) { + echo 'S'; + } + + echo "\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Checkstyle.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Checkstyle.php new file mode 100644 index 000000000..06a78e19f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Checkstyle.php @@ -0,0 +1,109 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; + +class Checkstyle implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new \XMLWriter; + $out->openMemory(); + $out->setIndent(true); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $out->startElement('file'); + $out->writeAttribute('name', $report['filename']); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement('error'); + $out->writeAttribute('line', $line); + $out->writeAttribute('column', $column); + $out->writeAttribute('severity', $error['type']); + $out->writeAttribute('message', $error['message']); + $out->writeAttribute('source', $error['source']); + $out->endElement(); + } + } + }//end foreach + + $out->endElement(); + echo $out->flush(); + + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a Checkstyle format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Code.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Code.php new file mode 100644 index 000000000..47c5581e2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Code.php @@ -0,0 +1,362 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Code implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + // How many lines to show about and below the error line. + $surroundingLines = 2; + + $file = $report['filename']; + $tokens = $phpcsFile->getTokens(); + if (empty($tokens) === true) { + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $startTime = microtime(true); + echo 'CODE report is parsing '.basename($file).' '; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "CODE report is forcing parse of $file".PHP_EOL; + } + + try { + $phpcsFile->parse(); + } catch (\Exception $e) { + // This is a second parse, so ignore exceptions. + // They would have been added to the file's error list already. + } + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + echo PHP_EOL; + } + + $tokens = $phpcsFile->getTokens(); + }//end if + + // Create an array that maps lines to the first token on the line. + $lineTokens = []; + $lastLine = 0; + $stackPtr = 0; + foreach ($tokens as $stackPtr => $token) { + if ($token['line'] !== $lastLine) { + if ($lastLine > 0) { + $lineTokens[$lastLine]['end'] = ($stackPtr - 1); + } + + $lastLine++; + $lineTokens[$lastLine] = [ + 'start' => $stackPtr, + 'end' => null, + ]; + } + } + + // Make sure the last token in the file sits on an imaginary + // last line so it is easier to generate code snippets at the + // end of the file. + $lineTokens[$lastLine]['end'] = $stackPtr; + + // Determine the longest code line we will be showing. + $maxSnippetLength = 0; + $eolLen = strlen($phpcsFile->eolChar); + foreach ($report['messages'] as $line => $lineErrors) { + $startLine = max(($line - $surroundingLines), 1); + $endLine = min(($line + $surroundingLines), $lastLine); + + $maxLineNumLength = strlen($endLine); + + for ($i = $startLine; $i <= $endLine; $i++) { + if ($i === 1) { + continue; + } + + $lineLength = ($tokens[($lineTokens[$i]['start'] - 1)]['column'] + $tokens[($lineTokens[$i]['start'] - 1)]['length'] - $eolLen); + $maxSnippetLength = max($lineLength, $maxSnippetLength); + } + } + + $maxSnippetLength += ($maxLineNumLength + 8); + + // Determine the longest error message we will be showing. + $maxErrorLength = 0; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $length = strlen($error['message']); + if ($showSources === true) { + $length += (strlen($error['source']) + 3); + } + + $maxErrorLength = max($maxErrorLength, ($length + 1)); + } + } + } + + // The padding that all lines will require that are printing an error message overflow. + if ($report['warnings'] > 0) { + $typeLength = 7; + } else { + $typeLength = 5; + } + + $errorPadding = str_repeat(' ', ($maxLineNumLength + 7)); + $errorPadding .= str_repeat(' ', $typeLength); + $errorPadding .= ' '; + if ($report['fixable'] > 0) { + $errorPadding .= ' '; + } + + $errorPaddingLength = strlen($errorPadding); + + // The maximum amount of space an error message can use. + $maxErrorSpace = ($width - $errorPaddingLength); + if ($showSources === true) { + // Account for the chars used to print colors. + $maxErrorSpace += 8; + } + + // Figure out the max report width we need and can use. + $fileLength = strlen($file); + $maxWidth = max(($fileLength + 6), ($maxErrorLength + $errorPaddingLength)); + $width = max(min($width, $maxWidth), $maxSnippetLength); + if ($width < 70) { + $width = 70; + } + + // Print the file header. + echo PHP_EOL."\033[1mFILE: "; + if ($fileLength <= ($width - 6)) { + echo $file; + } else { + echo '...'.substr($file, ($fileLength - ($width - 6))); + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + echo "\033[1m".'FOUND '.$report['errors'].' ERROR'; + if ($report['errors'] !== 1) { + echo 'S'; + } + + if ($report['warnings'] > 0) { + echo ' AND '.$report['warnings'].' WARNING'; + if ($report['warnings'] !== 1) { + echo 'S'; + } + } + + echo ' AFFECTING '.count($report['messages']).' LINE'; + if (count($report['messages']) !== 1) { + echo 'S'; + } + + echo "\033[0m".PHP_EOL; + + foreach ($report['messages'] as $line => $lineErrors) { + $startLine = max(($line - $surroundingLines), 1); + $endLine = min(($line + $surroundingLines), $lastLine); + + $snippet = ''; + if (isset($lineTokens[$startLine]) === true) { + for ($i = $lineTokens[$startLine]['start']; $i <= $lineTokens[$endLine]['end']; $i++) { + $snippetLine = $tokens[$i]['line']; + if ($lineTokens[$snippetLine]['start'] === $i) { + // Starting a new line. + if ($snippetLine === $line) { + $snippet .= "\033[1m".'>> '; + } else { + $snippet .= ' '; + } + + $snippet .= str_repeat(' ', ($maxLineNumLength - strlen($snippetLine))); + $snippet .= $snippetLine.': '; + if ($snippetLine === $line) { + $snippet .= "\033[0m"; + } + } + + if (isset($tokens[$i]['orig_content']) === true) { + $tokenContent = $tokens[$i]['orig_content']; + } else { + $tokenContent = $tokens[$i]['content']; + } + + if (strpos($tokenContent, "\t") !== false) { + $token = $tokens[$i]; + $token['content'] = $tokenContent; + if (stripos(PHP_OS, 'WIN') === 0) { + $tab = "\000"; + } else { + $tab = "\033[30;1m»\033[0m"; + } + + $phpcsFile->tokenizer->replaceTabsInToken($token, $tab, "\000"); + $tokenContent = $token['content']; + } + + $tokenContent = Util\Common::prepareForOutput($tokenContent, ["\r", "\n", "\t"]); + $tokenContent = str_replace("\000", ' ', $tokenContent); + + $underline = false; + if ($snippetLine === $line && isset($lineErrors[$tokens[$i]['column']]) === true) { + $underline = true; + } + + // Underline invisible characters as well. + if ($underline === true && trim($tokenContent) === '') { + $snippet .= "\033[4m".' '."\033[0m".$tokenContent; + } else { + if ($underline === true) { + $snippet .= "\033[4m"; + } + + $snippet .= $tokenContent; + + if ($underline === true) { + $snippet .= "\033[0m"; + } + } + }//end for + }//end if + + echo str_repeat('-', $width).PHP_EOL; + + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $padding = ($maxLineNumLength - strlen($line)); + echo 'LINE '.str_repeat(' ', $padding).$line.': '; + + if ($error['type'] === 'ERROR') { + echo "\033[31mERROR\033[0m"; + if ($report['warnings'] > 0) { + echo ' '; + } + } else { + echo "\033[33mWARNING\033[0m"; + } + + echo ' '; + if ($report['fixable'] > 0) { + echo '['; + if ($error['fixable'] === true) { + echo 'x'; + } else { + echo ' '; + } + + echo '] '; + } + + $message = $error['message']; + $message = str_replace("\n", "\n".$errorPadding, $message); + if ($showSources === true) { + $message = "\033[1m".$message."\033[0m".' ('.$error['source'].')'; + } + + $errorMsg = wordwrap( + $message, + $maxErrorSpace, + PHP_EOL.$errorPadding + ); + + echo $errorMsg.PHP_EOL; + }//end foreach + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo rtrim($snippet).PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + if ($report['fixable'] > 0) { + echo "\033[1m".'PHPCBF CAN FIX THE '.$report['fixable'].' MARKED SNIFF VIOLATIONS AUTOMATICALLY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + if ($cachedData === '') { + return; + } + + echo $cachedData; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Csv.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Csv.php new file mode 100644 index 000000000..6db7ecfc1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Csv.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Csv implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $filename = str_replace('"', '\"', $report['filename']); + $message = str_replace('"', '\"', $error['message']); + $type = strtolower($error['type']); + $source = $error['source']; + $severity = $error['severity']; + $fixable = (int) $error['fixable']; + echo "\"$filename\",$line,$column,$type,\"$message\",$source,$severity,$fixable".PHP_EOL; + } + } + } + + return true; + + }//end generateFileReport() + + + /** + * Generates a csv report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo 'File,Line,Column,Type,Message,Source,Severity,Fixable'.PHP_EOL; + echo $cachedData; + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Diff.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Diff.php new file mode 100644 index 000000000..ce4b31fc0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Diff.php @@ -0,0 +1,130 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Diff implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $errors = $phpcsFile->getFixableCount(); + if ($errors === 0) { + return false; + } + + $phpcsFile->disableCaching(); + $tokens = $phpcsFile->getTokens(); + if (empty($tokens) === true) { + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $startTime = microtime(true); + echo 'DIFF report is parsing '.basename($report['filename']).' '; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo 'DIFF report is forcing parse of '.$report['filename'].PHP_EOL; + } + + $phpcsFile->parse(); + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + echo PHP_EOL; + } + + $phpcsFile->fixer->startFile($phpcsFile); + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + ob_end_clean(); + echo "\t*** START FILE FIXING ***".PHP_EOL; + } + + $fixed = $phpcsFile->fixer->fixFile(); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END FILE FIXING ***".PHP_EOL; + ob_start(); + } + + if ($fixed === false) { + return false; + } + + $diff = $phpcsFile->fixer->generateDiff(); + if ($diff === '') { + // Nothing to print. + return false; + } + + echo $diff.PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo $cachedData; + if ($toScreen === true && $cachedData !== '') { + echo PHP_EOL; + } + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Emacs.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Emacs.php new file mode 100644 index 000000000..3555f5541 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Emacs.php @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Emacs implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $message = $error['message']; + if ($showSources === true) { + $message .= ' ('.$error['source'].')'; + } + + $type = strtolower($error['type']); + echo $report['filename'].':'.$line.':'.$column.': '.$type.' - '.$message.PHP_EOL; + } + } + } + + return true; + + }//end generateFileReport() + + + /** + * Generates an emacs report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo $cachedData; + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Full.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Full.php new file mode 100644 index 000000000..084bc8aa5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Full.php @@ -0,0 +1,231 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Full implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + // The length of the word ERROR or WARNING; used for padding. + if ($report['warnings'] > 0) { + $typeLength = 7; + } else { + $typeLength = 5; + } + + // Work out the max line number length for formatting. + $maxLineNumLength = max(array_map('strlen', array_keys($report['messages']))); + + // The padding that all lines will require that are + // printing an error message overflow. + $paddingLine2 = str_repeat(' ', ($maxLineNumLength + 1)); + $paddingLine2 .= ' | '; + $paddingLine2 .= str_repeat(' ', $typeLength); + $paddingLine2 .= ' | '; + if ($report['fixable'] > 0) { + $paddingLine2 .= ' '; + } + + $paddingLength = strlen($paddingLine2); + + // Make sure the report width isn't too big. + $maxErrorLength = 0; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $length = strlen($error['message']); + if ($showSources === true) { + $length += (strlen($error['source']) + 3); + } + + $maxErrorLength = max($maxErrorLength, ($length + 1)); + } + } + } + + $file = $report['filename']; + $fileLength = strlen($file); + $maxWidth = max(($fileLength + 6), ($maxErrorLength + $paddingLength)); + $width = min($width, $maxWidth); + if ($width < 70) { + $width = 70; + } + + echo PHP_EOL."\033[1mFILE: "; + if ($fileLength <= ($width - 6)) { + echo $file; + } else { + echo '...'.substr($file, ($fileLength - ($width - 6))); + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + echo "\033[1m".'FOUND '.$report['errors'].' ERROR'; + if ($report['errors'] !== 1) { + echo 'S'; + } + + if ($report['warnings'] > 0) { + echo ' AND '.$report['warnings'].' WARNING'; + if ($report['warnings'] !== 1) { + echo 'S'; + } + } + + echo ' AFFECTING '.count($report['messages']).' LINE'; + if (count($report['messages']) !== 1) { + echo 'S'; + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + // The maximum amount of space an error message can use. + $maxErrorSpace = ($width - $paddingLength - 1); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $message = $error['message']; + $msgLines = [$message]; + if (strpos($message, "\n") !== false) { + $msgLines = explode("\n", $message); + } + + $errorMsg = ''; + $lastLine = (count($msgLines) - 1); + foreach ($msgLines as $k => $msgLine) { + if ($k === 0) { + if ($showSources === true) { + $errorMsg .= "\033[1m"; + } + } else { + $errorMsg .= PHP_EOL.$paddingLine2; + } + + if ($k === $lastLine && $showSources === true) { + $msgLine .= "\033[0m".' ('.$error['source'].')'; + } + + $errorMsg .= wordwrap( + $msgLine, + $maxErrorSpace, + PHP_EOL.$paddingLine2 + ); + } + + // The padding that goes on the front of the line. + $padding = ($maxLineNumLength - strlen($line)); + + echo ' '.str_repeat(' ', $padding).$line.' | '; + if ($error['type'] === 'ERROR') { + echo "\033[31mERROR\033[0m"; + if ($report['warnings'] > 0) { + echo ' '; + } + } else { + echo "\033[33mWARNING\033[0m"; + } + + echo ' | '; + if ($report['fixable'] > 0) { + echo '['; + if ($error['fixable'] === true) { + echo 'x'; + } else { + echo ' '; + } + + echo '] '; + } + + echo $errorMsg.PHP_EOL; + }//end foreach + }//end foreach + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + if ($report['fixable'] > 0) { + echo "\033[1m".'PHPCBF CAN FIX THE '.$report['fixable'].' MARKED SNIFF VIOLATIONS AUTOMATICALLY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + echo PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + if ($cachedData === '') { + return; + } + + echo $cachedData; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Gitblame.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Gitblame.php new file mode 100644 index 000000000..6427567f8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Gitblame.php @@ -0,0 +1,91 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Gitblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'GIT'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + $line = preg_replace('|\s+|', ' ', $line); + preg_match( + '|\(.+[0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]+\)|', + $line, + $blameParts + ); + + if (isset($blameParts[0]) === false) { + return false; + } + + $parts = explode(' ', $blameParts[0]); + + if (count($parts) < 2) { + return false; + } + + $parts = array_slice($parts, 0, (count($parts) - 2)); + $author = preg_replace('|\(|', '', implode(' ', $parts)); + return $author; + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $cwd = getcwd(); + + chdir(dirname($filename)); + $command = 'git blame --date=short "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + chdir($cwd); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Hgblame.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Hgblame.php new file mode 100644 index 000000000..f88a06836 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Hgblame.php @@ -0,0 +1,110 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Hgblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'MERCURIAL'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + $line = preg_replace('|\s+|', ' ', $line); + + preg_match( + '|(.+[0-9]{2}:[0-9]{2}:[0-9]{2}\s[0-9]{4}\s.[0-9]{4}:)|', + $line, + $blameParts + ); + + if (isset($blameParts[0]) === false) { + return false; + } + + $parts = explode(' ', $blameParts[0]); + + if (count($parts) < 6) { + return false; + } + + $parts = array_slice($parts, 0, (count($parts) - 6)); + + return trim(preg_replace('|<.+>|', '', implode(' ', $parts))); + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $cwd = getcwd(); + + $fileParts = explode(DIRECTORY_SEPARATOR, $filename); + $found = false; + $location = ''; + while (empty($fileParts) === false) { + array_pop($fileParts); + $location = implode(DIRECTORY_SEPARATOR, $fileParts); + if (is_dir($location.DIRECTORY_SEPARATOR.'.hg') === true) { + $found = true; + break; + } + } + + if ($found === true) { + chdir($location); + } else { + $error = 'ERROR: Could not locate .hg directory '.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $command = 'hg blame -u -d -v "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + chdir($cwd); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Info.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Info.php new file mode 100644 index 000000000..3181bcc54 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Info.php @@ -0,0 +1,172 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Info implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $metrics = $phpcsFile->getMetrics(); + foreach ($metrics as $metric => $data) { + foreach ($data['values'] as $value => $count) { + echo "$metric>>$value>>$count".PHP_EOL; + } + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the source of all errors and warnings. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $metrics = []; + foreach ($lines as $line) { + $parts = explode('>>', $line); + $metric = $parts[0]; + $value = $parts[1]; + $count = $parts[2]; + if (isset($metrics[$metric]) === false) { + $metrics[$metric] = []; + } + + if (isset($metrics[$metric][$value]) === false) { + $metrics[$metric][$value] = $count; + } else { + $metrics[$metric][$value] += $count; + } + } + + ksort($metrics); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER INFORMATION REPORT'."\033[0m".PHP_EOL; + echo str_repeat('-', 70).PHP_EOL; + + foreach ($metrics as $metric => $values) { + if (count($values) === 1) { + $count = reset($values); + $value = key($values); + + echo "$metric: \033[4m$value\033[0m [$count/$count, 100%]".PHP_EOL; + } else { + $totalCount = 0; + $valueWidth = 0; + foreach ($values as $value => $count) { + $totalCount += $count; + $valueWidth = max($valueWidth, strlen($value)); + } + + // Length of the total string, plus however many + // thousands separators there are. + $countWidth = strlen($totalCount); + $thousandSeparatorCount = floor($countWidth / 3); + $countWidth += $thousandSeparatorCount; + + // Account for 'total' line. + $valueWidth = max(5, $valueWidth); + + echo "$metric:".PHP_EOL; + + ksort($values, SORT_NATURAL); + arsort($values); + + $percentPrefixWidth = 0; + $percentWidth = 6; + foreach ($values as $value => $count) { + $percent = round(($count / $totalCount * 100), 2); + $percentPrefix = ''; + if ($percent === 0.00) { + $percent = 0.01; + $percentPrefix = '<'; + $percentPrefixWidth = 2; + $percentWidth = 4; + } + + printf( + "\t%-{$valueWidth}s => %{$countWidth}s (%{$percentPrefixWidth}s%{$percentWidth}.2f%%)".PHP_EOL, + $value, + number_format($count), + $percentPrefix, + $percent + ); + } + + echo "\t".str_repeat('-', ($valueWidth + $countWidth + 15)).PHP_EOL; + printf( + "\t%-{$valueWidth}s => %{$countWidth}s (100.00%%)".PHP_EOL, + 'total', + number_format($totalCount) + ); + }//end if + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', 70).PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Json.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Json.php new file mode 100644 index 000000000..59d8f305e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Json.php @@ -0,0 +1,106 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Json implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $filename = str_replace('\\', '\\\\', $report['filename']); + $filename = str_replace('"', '\"', $filename); + $filename = str_replace('/', '\/', $filename); + echo '"'.$filename.'":{'; + echo '"errors":'.$report['errors'].',"warnings":'.$report['warnings'].',"messages":['; + + $messages = ''; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['message'] = str_replace("\n", '\n', $error['message']); + $error['message'] = str_replace("\r", '\r', $error['message']); + $error['message'] = str_replace("\t", '\t', $error['message']); + + $fixable = false; + if ($error['fixable'] === true) { + $fixable = true; + } + + $messagesObject = (object) $error; + $messagesObject->line = $line; + $messagesObject->column = $column; + $messagesObject->fixable = $fixable; + + $messages .= json_encode($messagesObject).","; + } + } + }//end foreach + + echo rtrim($messages, ','); + echo ']},'; + + return true; + + }//end generateFileReport() + + + /** + * Generates a JSON report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo '{"totals":{"errors":'.$totalErrors.',"warnings":'.$totalWarnings.',"fixable":'.$totalFixable.'},"files":{'; + echo rtrim($cachedData, ','); + echo "}}".PHP_EOL; + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Junit.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Junit.php new file mode 100644 index 000000000..d3ede61d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Junit.php @@ -0,0 +1,131 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; + +class Junit implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new \XMLWriter; + $out->openMemory(); + $out->setIndent(true); + + $out->startElement('testsuite'); + $out->writeAttribute('name', $report['filename']); + $out->writeAttribute('errors', 0); + + if (count($report['messages']) === 0) { + $out->writeAttribute('tests', 1); + $out->writeAttribute('failures', 0); + + $out->startElement('testcase'); + $out->writeAttribute('name', $report['filename']); + $out->endElement(); + } else { + $failures = ($report['errors'] + $report['warnings']); + $out->writeAttribute('tests', $failures); + $out->writeAttribute('failures', $failures); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $out->startElement('testcase'); + $out->writeAttribute('name', $error['source'].' at '.$report['filename']." ($line:$column)"); + + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement('failure'); + $out->writeAttribute('type', $error['type']); + $out->writeAttribute('message', $error['message']); + $out->endElement(); + + $out->endElement(); + } + } + } + }//end if + + $out->endElement(); + echo $out->flush(); + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + // Figure out the total number of tests. + $tests = 0; + $matches = []; + preg_match_all('/tests="([0-9]+)"/', $cachedData, $matches); + if (isset($matches[1]) === true) { + foreach ($matches[1] as $match) { + $tests += $match; + } + } + + $failures = ($totalErrors + $totalWarnings); + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Notifysend.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Notifysend.php new file mode 100644 index 000000000..084166223 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Notifysend.php @@ -0,0 +1,242 @@ + + * @author Greg Sherwood + * @copyright 2012-2014 Christian Weiske + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; + +class Notifysend implements Report +{ + + /** + * Notification timeout in milliseconds. + * + * @var integer + */ + protected $timeout = 3000; + + /** + * Path to notify-send command. + * + * @var string + */ + protected $path = 'notify-send'; + + /** + * Show "ok, all fine" messages. + * + * @var boolean + */ + protected $showOk = true; + + /** + * Version of installed notify-send executable. + * + * @var string + */ + protected $version = null; + + + /** + * Load configuration data. + */ + public function __construct() + { + $path = Config::getExecutablePath('notifysend'); + if ($path !== null) { + $this->path = Common::escapeshellcmd($path); + } + + $timeout = Config::getConfigData('notifysend_timeout'); + if ($timeout !== null) { + $this->timeout = (int) $timeout; + } + + $showOk = Config::getConfigData('notifysend_showok'); + if ($showOk !== null) { + $this->showOk = (bool) $showOk; + } + + $this->version = str_replace( + 'notify-send ', + '', + exec($this->path.' --version') + ); + + }//end __construct() + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + echo $report['filename'].PHP_EOL; + + // We want this file counted in the total number + // of checked files even if it has no errors. + return true; + + }//end generateFileReport() + + + /** + * Generates a summary of errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $checkedFiles = explode(PHP_EOL, trim($cachedData)); + + $msg = $this->generateMessage($checkedFiles, $totalErrors, $totalWarnings); + if ($msg === null) { + if ($this->showOk === true) { + $this->notifyAllFine(); + } + } else { + $this->notifyErrors($msg); + } + + }//end generate() + + + /** + * Generate the error message to show to the user. + * + * @param string[] $checkedFiles The files checked during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * + * @return string Error message or NULL if no error/warning found. + */ + protected function generateMessage($checkedFiles, $totalErrors, $totalWarnings) + { + if ($totalErrors === 0 && $totalWarnings === 0) { + // Nothing to print. + return null; + } + + $totalFiles = count($checkedFiles); + + $msg = ''; + if ($totalFiles > 1) { + $msg .= 'Checked '.$totalFiles.' files'.PHP_EOL; + } else { + $msg .= $checkedFiles[0].PHP_EOL; + } + + if ($totalWarnings > 0) { + $msg .= $totalWarnings.' warnings'.PHP_EOL; + } + + if ($totalErrors > 0) { + $msg .= $totalErrors.' errors'.PHP_EOL; + } + + return $msg; + + }//end generateMessage() + + + /** + * Tell the user that all is fine and no error/warning has been found. + * + * @return void + */ + protected function notifyAllFine() + { + $cmd = $this->getBasicCommand(); + $cmd .= ' -i info'; + $cmd .= ' "PHP CodeSniffer: Ok"'; + $cmd .= ' "All fine"'; + exec($cmd); + + }//end notifyAllFine() + + + /** + * Tell the user that errors/warnings have been found. + * + * @param string $msg Message to display. + * + * @return void + */ + protected function notifyErrors($msg) + { + $cmd = $this->getBasicCommand(); + $cmd .= ' -i error'; + $cmd .= ' "PHP CodeSniffer: Error"'; + $cmd .= ' '.escapeshellarg(trim($msg)); + exec($cmd); + + }//end notifyErrors() + + + /** + * Generate and return the basic notify-send command string to execute. + * + * @return string Shell command with common parameters. + */ + protected function getBasicCommand() + { + $cmd = $this->path; + $cmd .= ' --category dev.validate'; + $cmd .= ' -h int:transient:1'; + $cmd .= ' -t '.(int) $this->timeout; + if (version_compare($this->version, '0.7.3', '>=') === true) { + $cmd .= ' -a phpcs'; + } + + return $cmd; + + }//end getBasicCommand() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Report.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Report.php new file mode 100644 index 000000000..38f8a6298 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Report.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +interface Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80); + + + /** + * Generate the actual report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ); + + +}//end interface diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Source.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Source.php new file mode 100644 index 000000000..ce8c3cfec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Source.php @@ -0,0 +1,336 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Source implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $sources = []; + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $src = $error['source']; + if (isset($sources[$src]) === false) { + $sources[$src] = [ + 'fixable' => (int) $error['fixable'], + 'count' => 1, + ]; + } else { + $sources[$src]['count']++; + } + } + } + } + + foreach ($sources as $source => $data) { + echo $source.'>>'.$data['fixable'].'>>'.$data['count'].PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the source of all errors and warnings. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $sources = []; + $maxLength = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $source = $parts[0]; + $fixable = (bool) $parts[1]; + $count = $parts[2]; + + if (isset($sources[$source]) === false) { + if ($showSources === true) { + $parts = null; + $sniff = $source; + } else { + $parts = explode('.', $source); + if ($parts[0] === 'Internal') { + $parts[2] = $parts[1]; + $parts[1] = ''; + } + + $parts[1] = $this->makeFriendlyName($parts[1]); + + $sniff = $this->makeFriendlyName($parts[2]); + if (isset($parts[3]) === true) { + $name = $this->makeFriendlyName($parts[3]); + $name[0] = strtolower($name[0]); + $sniff .= ' '.$name; + unset($parts[3]); + } + + $parts[2] = $sniff; + }//end if + + $maxLength = max($maxLength, strlen($sniff)); + + $sources[$source] = [ + 'count' => $count, + 'fixable' => $fixable, + 'parts' => $parts, + ]; + } else { + $sources[$source]['count'] += $count; + }//end if + }//end foreach + + if ($showSources === true) { + $width = min($width, ($maxLength + 11)); + } else { + $width = min($width, ($maxLength + 41)); + } + + $width = max($width, 70); + + // Sort the data based on counts and source code. + $sourceCodes = array_keys($sources); + $counts = []; + foreach ($sources as $source => $data) { + $counts[$source] = $data['count']; + } + + array_multisort($counts, SORT_DESC, $sourceCodes, SORT_ASC, SORT_NATURAL, $sources); + + echo PHP_EOL."\033[1mPHP CODE SNIFFER VIOLATION SOURCE SUMMARY\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL."\033[1m"; + if ($showSources === true) { + if ($totalFixable > 0) { + echo ' SOURCE'.str_repeat(' ', ($width - 15)).'COUNT'.PHP_EOL; + } else { + echo 'SOURCE'.str_repeat(' ', ($width - 11)).'COUNT'.PHP_EOL; + } + } else { + if ($totalFixable > 0) { + echo ' STANDARD CATEGORY SNIFF'.str_repeat(' ', ($width - 44)).'COUNT'.PHP_EOL; + } else { + echo 'STANDARD CATEGORY SNIFF'.str_repeat(' ', ($width - 40)).'COUNT'.PHP_EOL; + } + } + + echo "\033[0m".str_repeat('-', $width).PHP_EOL; + + $fixableSources = 0; + + if ($showSources === true) { + $maxSniffWidth = ($width - 7); + } else { + $maxSniffWidth = ($width - 37); + } + + if ($totalFixable > 0) { + $maxSniffWidth -= 4; + } + + foreach ($sources as $source => $sourceData) { + if ($totalFixable > 0) { + echo '['; + if ($sourceData['fixable'] === true) { + echo 'x'; + $fixableSources++; + } else { + echo ' '; + } + + echo '] '; + } + + if ($showSources === true) { + if (strlen($source) > $maxSniffWidth) { + $source = substr($source, 0, $maxSniffWidth); + } + + echo $source; + if ($totalFixable > 0) { + echo str_repeat(' ', ($width - 9 - strlen($source))); + } else { + echo str_repeat(' ', ($width - 5 - strlen($source))); + } + } else { + $parts = $sourceData['parts']; + + if (strlen($parts[0]) > 8) { + $parts[0] = substr($parts[0], 0, ((strlen($parts[0]) - 8) * -1)); + } + + echo $parts[0].str_repeat(' ', (10 - strlen($parts[0]))); + + $category = $parts[1]; + if (strlen($category) > 18) { + $category = substr($category, 0, ((strlen($category) - 18) * -1)); + } + + echo $category.str_repeat(' ', (20 - strlen($category))); + + $sniff = $parts[2]; + if (strlen($sniff) > $maxSniffWidth) { + $sniff = substr($sniff, 0, $maxSniffWidth); + } + + if ($totalFixable > 0) { + echo $sniff.str_repeat(' ', ($width - 39 - strlen($sniff))); + } else { + echo $sniff.str_repeat(' ', ($width - 35 - strlen($sniff))); + } + }//end if + + echo $sourceData['count'].PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'A TOTAL OF '.($totalErrors + $totalWarnings).' SNIFF VIOLATION'; + if (($totalErrors + $totalWarnings) > 1) { + echo 'S'; + } + + echo ' WERE FOUND IN '.count($sources).' SOURCE'; + if (count($sources) !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + + /** + * Converts a camel caps name into a readable string. + * + * @param string $name The camel caps name to convert. + * + * @return string + */ + public function makeFriendlyName($name) + { + if (trim($name) === '') { + return ''; + } + + $friendlyName = ''; + $length = strlen($name); + + $lastWasUpper = false; + $lastWasNumeric = false; + for ($i = 0; $i < $length; $i++) { + if (is_numeric($name[$i]) === true) { + if ($lastWasNumeric === false) { + $friendlyName .= ' '; + } + + $lastWasUpper = false; + $lastWasNumeric = true; + } else { + $lastWasNumeric = false; + + $char = strtolower($name[$i]); + if ($char === $name[$i]) { + // Lowercase. + $lastWasUpper = false; + } else { + // Uppercase. + if ($lastWasUpper === false) { + $friendlyName .= ' '; + if ($i < ($length - 1)) { + $next = $name[($i + 1)]; + if (strtolower($next) === $next) { + // Next char is lowercase so it is a word boundary. + $name[$i] = strtolower($name[$i]); + } + } + } + + $lastWasUpper = true; + } + }//end if + + $friendlyName .= $name[$i]; + }//end for + + $friendlyName = trim($friendlyName); + $friendlyName[0] = strtoupper($friendlyName[0]); + + return $friendlyName; + + }//end makeFriendlyName() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Summary.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Summary.php new file mode 100644 index 000000000..8fe18e764 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Summary.php @@ -0,0 +1,183 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util; + +class Summary implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if (PHP_CODESNIFFER_VERBOSITY === 0 + && $report['errors'] === 0 + && $report['warnings'] === 0 + ) { + // Nothing to print. + return false; + } + + echo $report['filename'].'>>'.$report['errors'].'>>'.$report['warnings'].PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Generates a summary of errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $reportFiles = []; + $maxLength = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $fileLen = strlen($parts[0]); + $reportFiles[$parts[0]] = [ + 'errors' => $parts[1], + 'warnings' => $parts[2], + 'strlen' => $fileLen, + ]; + + $maxLength = max($maxLength, $fileLen); + } + + uksort( + $reportFiles, + function ($keyA, $keyB) { + $pathPartsA = explode(DIRECTORY_SEPARATOR, $keyA); + $pathPartsB = explode(DIRECTORY_SEPARATOR, $keyB); + + do { + $partA = array_shift($pathPartsA); + $partB = array_shift($pathPartsB); + } while ($partA === $partB && empty($pathPartsA) === false && empty($pathPartsB) === false); + + if (empty($pathPartsA) === false && empty($pathPartsB) === true) { + return 1; + } else if (empty($pathPartsA) === true && empty($pathPartsB) === false) { + return -1; + } else { + return strcasecmp($partA, $partB); + } + } + ); + + $width = min($width, ($maxLength + 21)); + $width = max($width, 70); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER REPORT SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'FILE'.str_repeat(' ', ($width - 20)).'ERRORS WARNINGS'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + foreach ($reportFiles as $file => $data) { + $padding = ($width - 18 - $data['strlen']); + if ($padding < 0) { + $file = '...'.substr($file, (($padding * -1) + 3)); + $padding = 0; + } + + echo $file.str_repeat(' ', $padding).' '; + if ($data['errors'] !== 0) { + echo "\033[31m".$data['errors']."\033[0m"; + echo str_repeat(' ', (8 - strlen((string) $data['errors']))); + } else { + echo '0 '; + } + + if ($data['warnings'] !== 0) { + echo "\033[33m".$data['warnings']."\033[0m"; + } else { + echo '0'; + } + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1mA TOTAL OF $totalErrors ERROR"; + if ($totalErrors !== 1) { + echo 'S'; + } + + echo ' AND '.$totalWarnings.' WARNING'; + if ($totalWarnings !== 1) { + echo 'S'; + } + + echo ' WERE FOUND IN '.$totalFiles.' FILE'; + if ($totalFiles !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Util\Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Svnblame.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Svnblame.php new file mode 100644 index 000000000..a7f65e154 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Svnblame.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Svnblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'SVN'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + preg_match('|\s*([^\s]+)\s+([^\s]+)|', $line, $blameParts); + + if (isset($blameParts[2]) === false) { + return false; + } + + return $blameParts[2]; + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $command = 'svn blame "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/VersionControl.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/VersionControl.php new file mode 100644 index 000000000..0f414567d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/VersionControl.php @@ -0,0 +1,376 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +abstract class VersionControl implements Report +{ + + /** + * The name of the report we want in the output. + * + * @var string + */ + protected $reportName = 'VERSION CONTROL'; + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $blames = $this->getBlameContent($report['filename']); + + $authorCache = []; + $praiseCache = []; + $sourceCache = []; + + foreach ($report['messages'] as $line => $lineErrors) { + $author = 'Unknown'; + if (isset($blames[($line - 1)]) === true) { + $blameAuthor = $this->getAuthor($blames[($line - 1)]); + if ($blameAuthor !== false) { + $author = $blameAuthor; + } + } + + if (isset($authorCache[$author]) === false) { + $authorCache[$author] = 0; + $praiseCache[$author] = [ + 'good' => 0, + 'bad' => 0, + ]; + } + + $praiseCache[$author]['bad']++; + + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $authorCache[$author]++; + + if ($showSources === true) { + $source = $error['source']; + if (isset($sourceCache[$author][$source]) === false) { + $sourceCache[$author][$source] = [ + 'count' => 1, + 'fixable' => $error['fixable'], + ]; + } else { + $sourceCache[$author][$source]['count']++; + } + } + } + } + + unset($blames[($line - 1)]); + }//end foreach + + // Now go through and give the authors some credit for + // all the lines that do not have errors. + foreach ($blames as $line) { + $author = $this->getAuthor($line); + if ($author === false) { + $author = 'Unknown'; + } + + if (isset($authorCache[$author]) === false) { + // This author doesn't have any errors. + if (PHP_CODESNIFFER_VERBOSITY === 0) { + continue; + } + + $authorCache[$author] = 0; + $praiseCache[$author] = [ + 'good' => 0, + 'bad' => 0, + ]; + } + + $praiseCache[$author]['good']++; + }//end foreach + + foreach ($authorCache as $author => $errors) { + echo "AUTHOR>>$author>>$errors".PHP_EOL; + } + + foreach ($praiseCache as $author => $praise) { + echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL; + } + + foreach ($sourceCache as $author => $sources) { + foreach ($sources as $source => $sourceData) { + $count = $sourceData['count']; + $fixable = (int) $sourceData['fixable']; + echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL; + } + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the author of all errors and warnings, as given by "version control blame". + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $errorsShown = ($totalErrors + $totalWarnings); + if ($errorsShown === 0) { + // Nothing to show. + return; + } + + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $authorCache = []; + $praiseCache = []; + $sourceCache = []; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + switch ($parts[0]) { + case 'AUTHOR': + if (isset($authorCache[$parts[1]]) === false) { + $authorCache[$parts[1]] = $parts[2]; + } else { + $authorCache[$parts[1]] += $parts[2]; + } + break; + case 'PRAISE': + if (isset($praiseCache[$parts[1]]) === false) { + $praiseCache[$parts[1]] = [ + 'good' => $parts[2], + 'bad' => $parts[3], + ]; + } else { + $praiseCache[$parts[1]]['good'] += $parts[2]; + $praiseCache[$parts[1]]['bad'] += $parts[3]; + } + break; + case 'SOURCE': + if (isset($praiseCache[$parts[1]]) === false) { + $praiseCache[$parts[1]] = []; + } + + if (isset($sourceCache[$parts[1]][$parts[2]]) === false) { + $sourceCache[$parts[1]][$parts[2]] = [ + 'count' => $parts[3], + 'fixable' => (bool) $parts[4], + ]; + } else { + $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3]; + } + break; + default: + break; + }//end switch + }//end foreach + + // Make sure the report width isn't too big. + $maxLength = 0; + foreach ($authorCache as $author => $count) { + $maxLength = max($maxLength, strlen($author)); + if ($showSources === true && isset($sourceCache[$author]) === true) { + foreach ($sourceCache[$author] as $source => $sourceData) { + if ($source === 'count') { + continue; + } + + $maxLength = max($maxLength, (strlen($source) + 9)); + } + } + } + + $width = min($width, ($maxLength + 30)); + $width = max($width, 70); + arsort($authorCache); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL."\033[1m"; + if ($showSources === true) { + echo 'AUTHOR SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } else { + echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + echo "\033[0m"; + + if ($showSources === true) { + $maxSniffWidth = ($width - 15); + + if ($totalFixable > 0) { + $maxSniffWidth -= 4; + } + } + + $fixableSources = 0; + + foreach ($authorCache as $author => $count) { + if ($praiseCache[$author]['good'] === 0) { + $percent = 0; + } else { + $total = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']); + $percent = round(($praiseCache[$author]['bad'] / $total * 100), 2); + } + + $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')'; + $authorPercent = '('.$percent.')'; + $line = str_repeat(' ', (6 - strlen($count))).$count; + $line = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line; + $line = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line; + $line = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line; + + if ($showSources === true) { + $line = "\033[1m$line\033[0m"; + } + + echo $line.PHP_EOL; + + if ($showSources === true && isset($sourceCache[$author]) === true) { + $errors = $sourceCache[$author]; + asort($errors); + $errors = array_reverse($errors); + + foreach ($errors as $source => $sourceData) { + if ($source === 'count') { + continue; + } + + $count = $sourceData['count']; + + $srcLength = strlen($source); + if ($srcLength > $maxSniffWidth) { + $source = substr($source, 0, $maxSniffWidth); + } + + $line = str_repeat(' ', (5 - strlen($count))).$count; + + echo ' '; + if ($totalFixable > 0) { + echo '['; + if ($sourceData['fixable'] === true) { + echo 'x'; + $fixableSources++; + } else { + echo ' '; + } + + echo '] '; + } + + echo $source; + if ($totalFixable > 0) { + echo str_repeat(' ', ($width - 18 - strlen($source))); + } else { + echo str_repeat(' ', ($width - 14 - strlen($source))); + } + + echo $line.PHP_EOL; + }//end foreach + }//end if + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION'; + if ($errorsShown !== 1) { + echo 'S'; + } + + echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR'; + if (count($authorCache) !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + if ($showSources === true) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m"; + } else { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m"; + } + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + abstract protected function getAuthor($line); + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + */ + abstract protected function getBlameContent($filename); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Reports/Xml.php b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Xml.php new file mode 100644 index 000000000..066383deb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Reports/Xml.php @@ -0,0 +1,126 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; + +class Xml implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new \XMLWriter; + $out->openMemory(); + $out->setIndent(true); + $out->setIndentString(' '); + $out->startDocument('1.0', 'UTF-8'); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $out->startElement('file'); + $out->writeAttribute('name', $report['filename']); + $out->writeAttribute('errors', $report['errors']); + $out->writeAttribute('warnings', $report['warnings']); + $out->writeAttribute('fixable', $report['fixable']); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement($error['type']); + $out->writeAttribute('line', $line); + $out->writeAttribute('column', $column); + $out->writeAttribute('source', $error['source']); + $out->writeAttribute('severity', $error['severity']); + $out->writeAttribute('fixable', (int) $error['fixable']); + $out->text($error['message']); + $out->endElement(); + } + } + }//end foreach + + $out->endElement(); + + // Remove the start of the document because we will + // add that manually later. We only have it in here to + // properly set the encoding. + $content = $out->flush(); + if (strpos($content, PHP_EOL) !== false) { + $content = substr($content, (strpos($content, PHP_EOL) + strlen(PHP_EOL))); + } else if (strpos($content, "\n") !== false) { + $content = substr($content, (strpos($content, "\n") + 1)); + } + + echo $content; + + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Ruleset.php b/kirki-composer/squizlabs/php_codesniffer/src/Ruleset.php new file mode 100644 index 000000000..7e659706c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Ruleset.php @@ -0,0 +1,1383 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util; + +class Ruleset +{ + + /** + * The name of the coding standard being used. + * + * If a top-level standard includes other standards, or sniffs + * from other standards, only the name of the top-level standard + * will be stored in here. + * + * If multiple top-level standards are being loaded into + * a single ruleset object, this will store a comma separated list + * of the top-level standard names. + * + * @var string + */ + public $name = ''; + + /** + * A list of file paths for the ruleset files being used. + * + * @var string[] + */ + public $paths = []; + + /** + * A list of regular expressions used to ignore specific sniffs for files and folders. + * + * Is also used to set global exclude patterns. + * The key is the regular expression and the value is the type + * of ignore pattern (absolute or relative). + * + * @var array + */ + public $ignorePatterns = []; + + /** + * A list of regular expressions used to include specific sniffs for files and folders. + * + * The key is the sniff code and the value is an array with + * the key being a regular expression and the value is the type + * of ignore pattern (absolute or relative). + * + * @var array> + */ + public $includePatterns = []; + + /** + * An array of sniff objects that are being used to check files. + * + * The key is the fully qualified name of the sniff class + * and the value is the sniff object. + * + * @var array + */ + public $sniffs = []; + + /** + * A mapping of sniff codes to fully qualified class names. + * + * The key is the sniff code and the value + * is the fully qualified name of the sniff class. + * + * @var array + */ + public $sniffCodes = []; + + /** + * An array of token types and the sniffs that are listening for them. + * + * The key is the token name being listened for and the value + * is the sniff object. + * + * @var array + */ + public $tokenListeners = []; + + /** + * An array of rules from the ruleset.xml file. + * + * It may be empty, indicating that the ruleset does not override + * any of the default sniff settings. + * + * @var array + */ + public $ruleset = []; + + /** + * The directories that the processed rulesets are in. + * + * @var string[] + */ + protected $rulesetDirs = []; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + private $config = null; + + + /** + * Initialise the ruleset that the run will use. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If no sniffs were registered. + */ + public function __construct(Config $config) + { + $this->config = $config; + $restrictions = $config->sniffs; + $exclusions = $config->exclude; + $sniffs = []; + + $standardPaths = []; + foreach ($config->standards as $standard) { + $installed = Util\Standards::getInstalledStandardPath($standard); + if ($installed === null) { + $standard = Util\Common::realpath($standard); + if (is_dir($standard) === true + && is_file(Util\Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml')) === true + ) { + $standard = Util\Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml'); + } + } else { + $standard = $installed; + } + + $standardPaths[] = $standard; + } + + foreach ($standardPaths as $standard) { + $ruleset = @simplexml_load_string(file_get_contents($standard)); + if ($ruleset !== false) { + $standardName = (string) $ruleset['name']; + if ($this->name !== '') { + $this->name .= ', '; + } + + $this->name .= $standardName; + + // Allow autoloading of custom files inside this standard. + if (isset($ruleset['namespace']) === true) { + $namespace = (string) $ruleset['namespace']; + } else { + $namespace = basename(dirname($standard)); + } + + Autoload::addSearchPath(dirname($standard), $namespace); + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === true && empty($restrictions) === false) { + // In unit tests, only register the sniffs that the test wants and not the entire standard. + try { + foreach ($restrictions as $restriction) { + $sniffs = array_merge($sniffs, $this->expandRulesetReference($restriction, dirname($standard))); + } + } catch (RuntimeException $e) { + // Sniff reference could not be expanded, which probably means this + // is an installed standard. Let the unit test system take care of + // setting the correct sniff for testing. + return; + } + + break; + } + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + echo "Registering sniffs in the $standardName standard... "; + if (count($config->standards) > 1 || PHP_CODESNIFFER_VERBOSITY > 2) { + echo PHP_EOL; + } + } + + $sniffs = array_merge($sniffs, $this->processRuleset($standard)); + }//end foreach + + // Ignore sniff restrictions if caching is on. + if ($config->cache === true) { + $restrictions = []; + $exclusions = []; + } + + $sniffRestrictions = []; + foreach ($restrictions as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $sniffRestrictions[$sniffName] = true; + } + + $sniffExclusions = []; + foreach ($exclusions as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $sniffExclusions[$sniffName] = true; + } + + $this->registerSniffs($sniffs, $sniffRestrictions, $sniffExclusions); + $this->populateTokenListeners(); + + $numSniffs = count($this->sniffs); + if (PHP_CODESNIFFER_VERBOSITY === 1) { + echo "DONE ($numSniffs sniffs registered)".PHP_EOL; + } + + if ($numSniffs === 0) { + throw new RuntimeException('No sniffs were registered'); + } + + }//end __construct() + + + /** + * Prints a report showing the sniffs contained in a standard. + * + * @return void + */ + public function explain() + { + $sniffs = array_keys($this->sniffCodes); + sort($sniffs); + + ob_start(); + + $lastStandard = null; + $lastCount = ''; + $sniffCount = count($sniffs); + + // Add a dummy entry to the end so we loop + // one last time and clear the output buffer. + $sniffs[] = ''; + + echo PHP_EOL."The $this->name standard contains $sniffCount sniffs".PHP_EOL; + + ob_start(); + + foreach ($sniffs as $i => $sniff) { + if ($i === $sniffCount) { + $currentStandard = null; + } else { + $currentStandard = substr($sniff, 0, strpos($sniff, '.')); + if ($lastStandard === null) { + $lastStandard = $currentStandard; + } + } + + if ($currentStandard !== $lastStandard) { + $sniffList = ob_get_contents(); + ob_end_clean(); + + echo PHP_EOL.$lastStandard.' ('.$lastCount.' sniff'; + if ($lastCount > 1) { + echo 's'; + } + + echo ')'.PHP_EOL; + echo str_repeat('-', (strlen($lastStandard.$lastCount) + 10)); + echo PHP_EOL; + echo $sniffList; + + $lastStandard = $currentStandard; + $lastCount = 0; + + if ($currentStandard === null) { + break; + } + + ob_start(); + }//end if + + echo ' '.$sniff.PHP_EOL; + $lastCount++; + }//end foreach + + }//end explain() + + + /** + * Processes a single ruleset and returns a list of the sniffs it represents. + * + * Rules founds within the ruleset are processed immediately, but sniff classes + * are not registered by this method. + * + * @param string $rulesetPath The path to a ruleset XML file. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return string[] + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException - If the ruleset path is invalid. + * - If a specified autoload file could not be found. + */ + public function processRuleset($rulesetPath, $depth=0) + { + $rulesetPath = Util\Common::realpath($rulesetPath); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo 'Processing ruleset '.Util\Common::stripBasepath($rulesetPath, $this->config->basepath).PHP_EOL; + } + + libxml_use_internal_errors(true); + $ruleset = simplexml_load_string(file_get_contents($rulesetPath)); + if ($ruleset === false) { + $errorMsg = "Ruleset $rulesetPath is not valid".PHP_EOL; + $errors = libxml_get_errors(); + foreach ($errors as $error) { + $errorMsg .= '- On line '.$error->line.', column '.$error->column.': '.$error->message; + } + + libxml_clear_errors(); + throw new RuntimeException($errorMsg); + } + + libxml_use_internal_errors(false); + + $ownSniffs = []; + $includedSniffs = []; + $excludedSniffs = []; + + $this->paths[] = $rulesetPath; + $rulesetDir = dirname($rulesetPath); + $this->rulesetDirs[] = $rulesetDir; + + $sniffDir = $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs'; + if (is_dir($sniffDir) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\tAdding sniff files from ".Util\Common::stripBasepath($sniffDir, $this->config->basepath).' directory'.PHP_EOL; + } + + $ownSniffs = $this->expandSniffDirectory($sniffDir, $depth); + } + + // Include custom autoloaders. + foreach ($ruleset->{'autoload'} as $autoload) { + if ($this->shouldProcessElement($autoload) === false) { + continue; + } + + $autoloadPath = (string) $autoload; + + // Try relative autoload paths first. + $relativePath = Util\Common::realPath(dirname($rulesetPath).DIRECTORY_SEPARATOR.$autoloadPath); + + if ($relativePath !== false && is_file($relativePath) === true) { + $autoloadPath = $relativePath; + } else if (is_file($autoloadPath) === false) { + throw new RuntimeException('The specified autoload file "'.$autoload.'" does not exist'); + } + + include_once $autoloadPath; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> included autoloader $autoloadPath".PHP_EOL; + } + }//end foreach + + // Process custom sniff config settings. + foreach ($ruleset->{'config'} as $config) { + if ($this->shouldProcessElement($config) === false) { + continue; + } + + Config::setConfigData((string) $config['name'], (string) $config['value'], true); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set config value ".(string) $config['name'].': '.(string) $config['value'].PHP_EOL; + } + } + + foreach ($ruleset->rule as $rule) { + if (isset($rule['ref']) === false + || $this->shouldProcessElement($rule) === false + ) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\tProcessing rule \"".$rule['ref'].'"'.PHP_EOL; + } + + $expandedSniffs = $this->expandRulesetReference((string) $rule['ref'], $rulesetDir, $depth); + $newSniffs = array_diff($expandedSniffs, $includedSniffs); + $includedSniffs = array_merge($includedSniffs, $expandedSniffs); + + $parts = explode('.', $rule['ref']); + if (count($parts) === 4 + && $parts[0] !== '' + && $parts[1] !== '' + && $parts[2] !== '' + ) { + $sniffCode = $parts[0].'.'.$parts[1].'.'.$parts[2]; + if (isset($this->ruleset[$sniffCode]['severity']) === true + && $this->ruleset[$sniffCode]['severity'] === 0 + ) { + // This sniff code has already been turned off, but now + // it is being explicitly included again, so turn it back on. + $this->ruleset[(string) $rule['ref']]['severity'] = 5; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* disabling sniff exclusion for specific message code *".PHP_EOL; + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to 5".PHP_EOL; + } + } else if (empty($newSniffs) === false) { + $newSniff = $newSniffs[0]; + if (in_array($newSniff, $ownSniffs, true) === false) { + // Including a sniff that hasn't been included higher up, but + // only including a single message from it. So turn off all messages in + // the sniff, except this one. + $this->ruleset[$sniffCode]['severity'] = 0; + $this->ruleset[(string) $rule['ref']]['severity'] = 5; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\tExcluding sniff \"".$sniffCode.'" except for "'.$parts[3].'"'.PHP_EOL; + } + } + }//end if + }//end if + + if (isset($rule->exclude) === true) { + foreach ($rule->exclude as $exclude) { + if (isset($exclude['name']) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* ignoring empty exclude rule *".PHP_EOL; + echo "\t\t\t=> ".$exclude->asXML().PHP_EOL; + } + + continue; + } + + if ($this->shouldProcessElement($exclude) === false) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\tExcluding rule \"".$exclude['name'].'"'.PHP_EOL; + } + + // Check if a single code is being excluded, which is a shortcut + // for setting the severity of the message to 0. + $parts = explode('.', $exclude['name']); + if (count($parts) === 4) { + $this->ruleset[(string) $exclude['name']]['severity'] = 0; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to 0".PHP_EOL; + } + } else { + $excludedSniffs = array_merge( + $excludedSniffs, + $this->expandRulesetReference((string) $exclude['name'], $rulesetDir, ($depth + 1)) + ); + } + }//end foreach + }//end if + + $this->processRule($rule, $newSniffs, $depth); + }//end foreach + + // Process custom command line arguments. + $cliArgs = []; + foreach ($ruleset->{'arg'} as $arg) { + if ($this->shouldProcessElement($arg) === false) { + continue; + } + + if (isset($arg['name']) === true) { + $argString = '--'.(string) $arg['name']; + if (isset($arg['value']) === true) { + $argString .= '='.(string) $arg['value']; + } + } else { + $argString = '-'.(string) $arg['value']; + } + + $cliArgs[] = $argString; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set command line value $argString".PHP_EOL; + } + }//end foreach + + // Set custom php ini values as CLI args. + foreach ($ruleset->{'ini'} as $arg) { + if ($this->shouldProcessElement($arg) === false) { + continue; + } + + if (isset($arg['name']) === false) { + continue; + } + + $name = (string) $arg['name']; + $argString = $name; + if (isset($arg['value']) === true) { + $value = (string) $arg['value']; + $argString .= "=$value"; + } else { + $value = 'true'; + } + + $cliArgs[] = '-d'; + $cliArgs[] = $argString; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set PHP ini value $name to $value".PHP_EOL; + } + }//end foreach + + if (empty($this->config->files) === true) { + // Process hard-coded file paths. + foreach ($ruleset->{'file'} as $file) { + $file = (string) $file; + $cliArgs[] = $file; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> added \"$file\" to the file list".PHP_EOL; + } + } + } + + if (empty($cliArgs) === false) { + // Change the directory so all relative paths are worked + // out based on the location of the ruleset instead of + // the location of the user. + $inPhar = Util\Common::isPharFile($rulesetDir); + if ($inPhar === false) { + $currentDir = getcwd(); + chdir($rulesetDir); + } + + $this->config->setCommandLineValues($cliArgs); + + if ($inPhar === false) { + chdir($currentDir); + } + } + + // Process custom ignore pattern rules. + foreach ($ruleset->{'exclude-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->ignorePatterns[(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> added global ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL; + } + } + + $includedSniffs = array_unique(array_merge($ownSniffs, $includedSniffs)); + $excludedSniffs = array_unique($excludedSniffs); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $included = count($includedSniffs); + $excluded = count($excludedSniffs); + echo str_repeat("\t", $depth); + echo "=> Ruleset processing complete; included $included sniffs and excluded $excluded".PHP_EOL; + } + + // Merge our own sniff list with our externally included + // sniff list, but filter out any excluded sniffs. + $files = []; + foreach ($includedSniffs as $sniff) { + if (in_array($sniff, $excludedSniffs, true) === true) { + continue; + } else { + $files[] = Util\Common::realpath($sniff); + } + } + + return $files; + + }//end processRuleset() + + + /** + * Expands a directory into a list of sniff files within. + * + * @param string $directory The path to a directory. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return array + */ + private function expandSniffDirectory($directory, $depth=0) + { + $sniffs = []; + + $rdi = new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS); + $di = new \RecursiveIteratorIterator($rdi, 0, \RecursiveIteratorIterator::CATCH_GET_CHILD); + + $dirLen = strlen($directory); + + foreach ($di as $file) { + $filename = $file->getFilename(); + + // Skip hidden files. + if (substr($filename, 0, 1) === '.') { + continue; + } + + // We are only interested in PHP and sniff files. + $fileParts = explode('.', $filename); + if (array_pop($fileParts) !== 'php') { + continue; + } + + $basename = basename($filename, '.php'); + if (substr($basename, -5) !== 'Sniff') { + continue; + } + + $path = $file->getPathname(); + + // Skip files in hidden directories within the Sniffs directory of this + // standard. We use the offset with strpos() to allow hidden directories + // before, valid example: + // /home/foo/.composer/vendor/squiz/custom_tool/MyStandard/Sniffs/... + if (strpos($path, DIRECTORY_SEPARATOR.'.', $dirLen) !== false) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($path, $this->config->basepath).PHP_EOL; + } + + $sniffs[] = $path; + }//end foreach + + return $sniffs; + + }//end expandSniffDirectory() + + + /** + * Expands a ruleset reference into a list of sniff files. + * + * @param string $ref The reference from the ruleset XML file. + * @param string $rulesetDir The directory of the ruleset XML file, used to + * evaluate relative paths. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the reference is invalid. + */ + private function expandRulesetReference($ref, $rulesetDir, $depth=0) + { + // Ignore internal sniffs codes as they are used to only + // hide and change internal messages. + if (substr($ref, 0, 9) === 'Internal.') { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* ignoring internal sniff code *".PHP_EOL; + } + + return []; + } + + // As sniffs can't begin with a full stop, assume references in + // this format are relative paths and attempt to convert them + // to absolute paths. If this fails, let the reference run through + // the normal checks and have it fail as normal. + if (substr($ref, 0, 1) === '.') { + $realpath = Util\Common::realpath($rulesetDir.'/'.$ref); + if ($realpath !== false) { + $ref = $realpath; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } + } + + // As sniffs can't begin with a tilde, assume references in + // this format are relative to the user's home directory. + if (substr($ref, 0, 2) === '~/') { + $realpath = Util\Common::realpath($ref); + if ($realpath !== false) { + $ref = $realpath; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } + } + + if (is_file($ref) === true) { + if (substr($ref, -9) === 'Sniff.php') { + // A single external sniff. + $this->rulesetDirs[] = dirname(dirname(dirname($ref))); + return [$ref]; + } + } else { + // See if this is a whole standard being referenced. + $path = Util\Standards::getInstalledStandardPath($ref); + if ($path !== null && Util\Common::isPharFile($path) === true && strpos($path, 'ruleset.xml') === false) { + // If the ruleset exists inside the phar file, use it. + if (file_exists($path.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { + $path .= DIRECTORY_SEPARATOR.'ruleset.xml'; + } else { + $path = null; + } + } + + if ($path !== null) { + $ref = $path; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } else if (is_dir($ref) === false) { + // Work out the sniff path. + $sepPos = strpos($ref, DIRECTORY_SEPARATOR); + if ($sepPos !== false) { + $stdName = substr($ref, 0, $sepPos); + $path = substr($ref, $sepPos); + } else { + $parts = explode('.', $ref); + $stdName = $parts[0]; + if (count($parts) === 1) { + // A whole standard? + $path = ''; + } else if (count($parts) === 2) { + // A directory of sniffs? + $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1]; + } else { + // A single sniff? + $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1].DIRECTORY_SEPARATOR.$parts[2].'Sniff.php'; + } + } + + $newRef = false; + $stdPath = Util\Standards::getInstalledStandardPath($stdName); + if ($stdPath !== null && $path !== '') { + if (Util\Common::isPharFile($stdPath) === true + && strpos($stdPath, 'ruleset.xml') === false + ) { + // Phar files can only return the directory, + // since ruleset can be omitted if building one standard. + $newRef = Util\Common::realpath($stdPath.$path); + } else { + $newRef = Util\Common::realpath(dirname($stdPath).$path); + } + } + + if ($newRef === false) { + // The sniff is not locally installed, so check if it is being + // referenced as a remote sniff outside the install. We do this + // by looking through all directories where we have found ruleset + // files before, looking for ones for this particular standard, + // and seeing if it is in there. + foreach ($this->rulesetDirs as $dir) { + if (strtolower(basename($dir)) !== strtolower($stdName)) { + continue; + } + + $newRef = Util\Common::realpath($dir.$path); + + if ($newRef !== false) { + $ref = $newRef; + } + } + } else { + $ref = $newRef; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Util\Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + }//end if + }//end if + + if (is_dir($ref) === true) { + if (is_file($ref.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { + // We are referencing an external coding standard. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a standard using directory name; processing *".PHP_EOL; + } + + return $this->processRuleset($ref.DIRECTORY_SEPARATOR.'ruleset.xml', ($depth + 2)); + } else { + // We are referencing a whole directory of sniffs. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a directory of sniffs *".PHP_EOL; + echo str_repeat("\t", $depth); + echo "\t\tAdding sniff files from directory".PHP_EOL; + } + + return $this->expandSniffDirectory($ref, ($depth + 1)); + } + } else { + if (is_file($ref) === false) { + $error = "Referenced sniff \"$ref\" does not exist"; + throw new RuntimeException($error); + } + + if (substr($ref, -9) === 'Sniff.php') { + // A single sniff. + return [$ref]; + } else { + // Assume an external ruleset.xml file. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a standard using ruleset path; processing *".PHP_EOL; + } + + return $this->processRuleset($ref, ($depth + 2)); + } + }//end if + + }//end expandRulesetReference() + + + /** + * Processes a rule from a ruleset XML file, overriding built-in defaults. + * + * @param \SimpleXMLElement $rule The rule object from a ruleset XML file. + * @param string[] $newSniffs An array of sniffs that got included by this rule. + * @param int $depth How many nested processing steps we are in. + * This is only used for debug output. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If rule settings are invalid. + */ + private function processRule($rule, $newSniffs, $depth=0) + { + $ref = (string) $rule['ref']; + $todo = [$ref]; + + $parts = explode('.', $ref); + $partsCount = count($parts); + if ($partsCount <= 2 + || $partsCount > count(array_filter($parts)) + || in_array($ref, $newSniffs) === true + ) { + // We are processing a standard, a category of sniffs or a relative path inclusion. + foreach ($newSniffs as $sniffFile) { + $parts = explode(DIRECTORY_SEPARATOR, $sniffFile); + if (count($parts) === 1 && DIRECTORY_SEPARATOR === '\\') { + // Path using forward slashes while running on Windows. + $parts = explode('/', $sniffFile); + } + + $sniffName = array_pop($parts); + $sniffCategory = array_pop($parts); + array_pop($parts); + $sniffStandard = array_pop($parts); + $todo[] = $sniffStandard.'.'.$sniffCategory.'.'.substr($sniffName, 0, -9); + } + } + + foreach ($todo as $code) { + // Custom severity. + if (isset($rule->severity) === true + && $this->shouldProcessElement($rule->severity) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $this->ruleset[$code]['severity'] = (int) $rule->severity; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to ".(int) $rule->severity; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } + + // Custom message type. + if (isset($rule->type) === true + && $this->shouldProcessElement($rule->type) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $type = strtolower((string) $rule->type); + if ($type !== 'error' && $type !== 'warning') { + throw new RuntimeException("Message type \"$type\" is invalid; must be \"error\" or \"warning\""); + } + + $this->ruleset[$code]['type'] = $type; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> message type set to ".(string) $rule->type; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + }//end if + + // Custom message. + if (isset($rule->message) === true + && $this->shouldProcessElement($rule->message) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $this->ruleset[$code]['message'] = (string) $rule->message; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> message set to ".(string) $rule->message; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } + + // Custom properties. + if (isset($rule->properties) === true + && $this->shouldProcessElement($rule->properties) === true + ) { + foreach ($rule->properties->property as $prop) { + if ($this->shouldProcessElement($prop) === false) { + continue; + } + + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = [ + 'properties' => [], + ]; + } else if (isset($this->ruleset[$code]['properties']) === false) { + $this->ruleset[$code]['properties'] = []; + } + + $name = (string) $prop['name']; + if (isset($prop['type']) === true + && (string) $prop['type'] === 'array' + ) { + $values = []; + if (isset($prop['extend']) === true + && (string) $prop['extend'] === 'true' + && isset($this->ruleset[$code]['properties'][$name]) === true + ) { + $values = $this->ruleset[$code]['properties'][$name]; + } + + if (isset($prop->element) === true) { + $printValue = ''; + foreach ($prop->element as $element) { + if ($this->shouldProcessElement($element) === false) { + continue; + } + + $value = (string) $element['value']; + if (isset($element['key']) === true) { + $key = (string) $element['key']; + $values[$key] = $value; + $printValue .= $key.'=>'.$value.','; + } else { + $values[] = $value; + $printValue .= $value.','; + } + } + + $printValue = rtrim($printValue, ','); + } else { + $value = (string) $prop['value']; + $printValue = $value; + foreach (explode(',', $value) as $val) { + list($k, $v) = explode('=>', $val.'=>'); + if ($v !== '') { + $values[trim($k)] = trim($v); + } else { + $values[] = trim($k); + } + } + }//end if + + $this->ruleset[$code]['properties'][$name] = $values; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> array property \"$name\" set to \"$printValue\""; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } else { + $this->ruleset[$code]['properties'][$name] = (string) $prop['value']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> property \"$name\" set to \"".(string) $prop['value'].'"'; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + }//end if + }//end foreach + }//end if + + // Ignore patterns. + foreach ($rule->{'exclude-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($this->ignorePatterns[$code]) === false) { + $this->ignorePatterns[$code] = []; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->ignorePatterns[$code][(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> added rule-specific ".(string) $pattern['type'].' ignore pattern'; + if ($code !== $ref) { + echo " for $code"; + } + + echo ': '.(string) $pattern.PHP_EOL; + } + }//end foreach + + // Include patterns. + foreach ($rule->{'include-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($this->includePatterns[$code]) === false) { + $this->includePatterns[$code] = []; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->includePatterns[$code][(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> added rule-specific ".(string) $pattern['type'].' include pattern'; + if ($code !== $ref) { + echo " for $code"; + } + + echo ': '.(string) $pattern.PHP_EOL; + } + }//end foreach + }//end foreach + + }//end processRule() + + + /** + * Determine if an element should be processed or ignored. + * + * @param \SimpleXMLElement $element An object from a ruleset XML file. + * + * @return bool + */ + private function shouldProcessElement($element) + { + if (isset($element['phpcbf-only']) === false + && isset($element['phpcs-only']) === false + ) { + // No exceptions are being made. + return true; + } + + if (PHP_CODESNIFFER_CBF === true + && isset($element['phpcbf-only']) === true + && (string) $element['phpcbf-only'] === 'true' + ) { + return true; + } + + if (PHP_CODESNIFFER_CBF === false + && isset($element['phpcs-only']) === true + && (string) $element['phpcs-only'] === 'true' + ) { + return true; + } + + return false; + + }//end shouldProcessElement() + + + /** + * Loads and stores sniffs objects used for sniffing files. + * + * @param array $files Paths to the sniff files to register. + * @param array $restrictions The sniff class names to restrict the allowed + * listeners to. + * @param array $exclusions The sniff class names to exclude from the + * listeners list. + * + * @return void + */ + public function registerSniffs($files, $restrictions, $exclusions) + { + $listeners = []; + + foreach ($files as $file) { + // Work out where the position of /StandardName/Sniffs/... is + // so we can determine what the class will be called. + $sniffPos = strrpos($file, DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR); + if ($sniffPos === false) { + continue; + } + + $slashPos = strrpos(substr($file, 0, $sniffPos), DIRECTORY_SEPARATOR); + if ($slashPos === false) { + continue; + } + + $className = Autoload::loadFile($file); + $compareName = Util\Common::cleanSniffClass($className); + + // If they have specified a list of sniffs to restrict to, check + // to see if this sniff is allowed. + if (empty($restrictions) === false + && isset($restrictions[$compareName]) === false + ) { + continue; + } + + // If they have specified a list of sniffs to exclude, check + // to see if this sniff is allowed. + if (empty($exclusions) === false + && isset($exclusions[$compareName]) === true + ) { + continue; + } + + // Skip abstract classes. + $reflection = new \ReflectionClass($className); + if ($reflection->isAbstract() === true) { + continue; + } + + $listeners[$className] = $className; + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "Registered $className".PHP_EOL; + } + }//end foreach + + $this->sniffs = $listeners; + + }//end registerSniffs() + + + /** + * Populates the array of PHP_CodeSniffer_Sniff objects for this file. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If sniff registration fails. + */ + public function populateTokenListeners() + { + // Construct a list of listeners indexed by token being listened for. + $this->tokenListeners = []; + + foreach ($this->sniffs as $sniffClass => $sniffObject) { + $this->sniffs[$sniffClass] = null; + $this->sniffs[$sniffClass] = new $sniffClass(); + + $sniffCode = Util\Common::getSniffCode($sniffClass); + $this->sniffCodes[$sniffCode] = $sniffClass; + + // Set custom properties. + if (isset($this->ruleset[$sniffCode]['properties']) === true) { + foreach ($this->ruleset[$sniffCode]['properties'] as $name => $value) { + $this->setSniffProperty($sniffClass, $name, $value); + } + } + + $tokenizers = []; + $vars = get_class_vars($sniffClass); + if (isset($vars['supportedTokenizers']) === true) { + foreach ($vars['supportedTokenizers'] as $tokenizer) { + $tokenizers[$tokenizer] = $tokenizer; + } + } else { + $tokenizers = ['PHP' => 'PHP']; + } + + $tokens = $this->sniffs[$sniffClass]->register(); + if (is_array($tokens) === false) { + $msg = "Sniff $sniffClass register() method must return an array"; + throw new RuntimeException($msg); + } + + $ignorePatterns = []; + $patterns = $this->getIgnorePatterns($sniffCode); + foreach ($patterns as $pattern => $type) { + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + $ignorePatterns[] = strtr($pattern, $replacements); + } + + $includePatterns = []; + $patterns = $this->getIncludePatterns($sniffCode); + foreach ($patterns as $pattern => $type) { + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + $includePatterns[] = strtr($pattern, $replacements); + } + + foreach ($tokens as $token) { + if (isset($this->tokenListeners[$token]) === false) { + $this->tokenListeners[$token] = []; + } + + if (isset($this->tokenListeners[$token][$sniffClass]) === false) { + $this->tokenListeners[$token][$sniffClass] = [ + 'class' => $sniffClass, + 'source' => $sniffCode, + 'tokenizers' => $tokenizers, + 'ignore' => $ignorePatterns, + 'include' => $includePatterns, + ]; + } + } + }//end foreach + + }//end populateTokenListeners() + + + /** + * Set a single property for a sniff. + * + * @param string $sniffClass The class name of the sniff. + * @param string $name The name of the property to change. + * @param string $value The new value of the property. + * + * @return void + */ + public function setSniffProperty($sniffClass, $name, $value) + { + // Setting a property for a sniff we are not using. + if (isset($this->sniffs[$sniffClass]) === false) { + return; + } + + $name = trim($name); + if (is_string($value) === true) { + $value = trim($value); + } + + if ($value === '') { + $value = null; + } + + // Special case for booleans. + if ($value === 'true') { + $value = true; + } else if ($value === 'false') { + $value = false; + } else if (substr($name, -2) === '[]') { + $name = substr($name, 0, -2); + $values = []; + if ($value !== null) { + foreach (explode(',', $value) as $val) { + list($k, $v) = explode('=>', $val.'=>'); + if ($v !== '') { + $values[trim($k)] = trim($v); + } else { + $values[] = trim($k); + } + } + } + + $value = $values; + } + + $this->sniffs[$sniffClass]->$name = $value; + + }//end setSniffProperty() + + + /** + * Gets the array of ignore patterns. + * + * Optionally takes a listener to get ignore patterns specified + * for that sniff only. + * + * @param string $listener The listener to get patterns for. If NULL, all + * patterns are returned. + * + * @return array + */ + public function getIgnorePatterns($listener=null) + { + if ($listener === null) { + return $this->ignorePatterns; + } + + if (isset($this->ignorePatterns[$listener]) === true) { + return $this->ignorePatterns[$listener]; + } + + return []; + + }//end getIgnorePatterns() + + + /** + * Gets the array of include patterns. + * + * Optionally takes a listener to get include patterns specified + * for that sniff only. + * + * @param string $listener The listener to get patterns for. If NULL, all + * patterns are returned. + * + * @return array + */ + public function getIncludePatterns($listener=null) + { + if ($listener === null) { + return $this->includePatterns; + } + + if (isset($this->includePatterns[$listener]) === true) { + return $this->includePatterns[$listener]; + } + + return []; + + }//end getIncludePatterns() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Runner.php b/kirki-composer/squizlabs/php_codesniffer/src/Runner.php new file mode 100644 index 000000000..fa68ff51b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Runner.php @@ -0,0 +1,889 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Files\FileList; +use PHP_CodeSniffer\Util\Cache; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Standards; + +class Runner +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * The reporter used for generating reports after the run. + * + * @var \PHP_CodeSniffer\Reporter + */ + public $reporter = null; + + + /** + * Run the PHPCS script. + * + * @return array + */ + public function runPHPCS() + { + try { + Util\Timing::startTiming(); + Runner::checkRequirements(); + + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + + // Creating the Config object populates it with all required settings + // based on the CLI arguments provided to the script and any config + // values the user has set. + $this->config = new Config(); + + // Init the run and load the rulesets to set additional config vars. + $this->init(); + + // Print a list of sniffs in each of the supplied standards. + // We fudge the config here so that each standard is explained in isolation. + if ($this->config->explain === true) { + $standards = $this->config->standards; + foreach ($standards as $standard) { + $this->config->standards = [$standard]; + $ruleset = new Ruleset($this->config); + $ruleset->explain(); + } + + return 0; + } + + // Generate documentation for each of the supplied standards. + if ($this->config->generator !== null) { + $standards = $this->config->standards; + foreach ($standards as $standard) { + $this->config->standards = [$standard]; + $ruleset = new Ruleset($this->config); + $class = 'PHP_CodeSniffer\Generators\\'.$this->config->generator; + $generator = new $class($ruleset); + $generator->generate(); + } + + return 0; + } + + // Other report formats don't really make sense in interactive mode + // so we hard-code the full report here and when outputting. + // We also ensure parallel processing is off because we need to do one file at a time. + if ($this->config->interactive === true) { + $this->config->reports = ['full' => null]; + $this->config->parallel = 1; + $this->config->showProgress = false; + } + + // Disable caching if we are processing STDIN as we can't be 100% + // sure where the file came from or if it will change in the future. + if ($this->config->stdin === true) { + $this->config->cache = false; + } + + $numErrors = $this->run(); + + // Print all the reports for this run. + $toScreen = $this->reporter->printReports(); + + // Only print timer output if no reports were + // printed to the screen so we don't put additional output + // in something like an XML report. If we are printing to screen, + // the report types would have already worked out who should + // print the timer info. + if ($this->config->interactive === false + && ($toScreen === false + || (($this->reporter->totalErrors + $this->reporter->totalWarnings) === 0 && $this->config->showProgress === true)) + ) { + Util\Timing::printRunTime(); + } + } catch (DeepExitException $e) { + echo $e->getMessage(); + return $e->getCode(); + }//end try + + if ($numErrors === 0) { + // No errors found. + return 0; + } else if ($this->reporter->totalFixable === 0) { + // Errors found, but none of them can be fixed by PHPCBF. + return 1; + } else { + // Errors found, and some can be fixed by PHPCBF. + return 2; + } + + }//end runPHPCS() + + + /** + * Run the PHPCBF script. + * + * @return array + */ + public function runPHPCBF() + { + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', true); + } + + try { + Util\Timing::startTiming(); + Runner::checkRequirements(); + + // Creating the Config object populates it with all required settings + // based on the CLI arguments provided to the script and any config + // values the user has set. + $this->config = new Config(); + + // When processing STDIN, we can't output anything to the screen + // or it will end up mixed in with the file output. + if ($this->config->stdin === true) { + $this->config->verbosity = 0; + } + + // Init the run and load the rulesets to set additional config vars. + $this->init(); + + // When processing STDIN, we only process one file at a time and + // we don't process all the way through, so we can't use the parallel + // running system. + if ($this->config->stdin === true) { + $this->config->parallel = 1; + } + + // Override some of the command line settings that might break the fixes. + $this->config->generator = null; + $this->config->explain = false; + $this->config->interactive = false; + $this->config->cache = false; + $this->config->showSources = false; + $this->config->recordErrors = false; + $this->config->reportFile = null; + $this->config->reports = ['cbf' => null]; + + // If a standard tries to set command line arguments itself, some + // may be blocked because PHPCBF is running, so stop the script + // dying if any are found. + $this->config->dieOnUnknownArg = false; + + $this->run(); + $this->reporter->printReports(); + + echo PHP_EOL; + Util\Timing::printRunTime(); + } catch (DeepExitException $e) { + echo $e->getMessage(); + return $e->getCode(); + }//end try + + if ($this->reporter->totalFixed === 0) { + // Nothing was fixed by PHPCBF. + if ($this->reporter->totalFixable === 0) { + // Nothing found that could be fixed. + return 0; + } else { + // Something failed to fix. + return 2; + } + } + + if ($this->reporter->totalFixable === 0) { + // PHPCBF fixed all fixable errors. + return 1; + } + + // PHPCBF fixed some fixable errors, but others failed to fix. + return 2; + + }//end runPHPCBF() + + + /** + * Exits if the minimum requirements of PHP_CodeSniffer are not met. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the requirements are not met. + */ + public function checkRequirements() + { + // Check the PHP version. + if (PHP_VERSION_ID < 50400) { + $error = 'ERROR: PHP_CodeSniffer requires PHP version 5.4.0 or greater.'.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $requiredExtensions = [ + 'tokenizer', + 'xmlwriter', + 'SimpleXML', + ]; + $missingExtensions = []; + + foreach ($requiredExtensions as $extension) { + if (extension_loaded($extension) === false) { + $missingExtensions[] = $extension; + } + } + + if (empty($missingExtensions) === false) { + $last = array_pop($requiredExtensions); + $required = implode(', ', $requiredExtensions); + $required .= ' and '.$last; + + if (count($missingExtensions) === 1) { + $missing = $missingExtensions[0]; + } else { + $last = array_pop($missingExtensions); + $missing = implode(', ', $missingExtensions); + $missing .= ' and '.$last; + } + + $error = 'ERROR: PHP_CodeSniffer requires the %s extensions to be enabled. Please enable %s.'.PHP_EOL; + $error = sprintf($error, $required, $missing); + throw new DeepExitException($error, 3); + } + + }//end checkRequirements() + + + /** + * Init the rulesets and other high-level settings. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If a referenced standard is not installed. + */ + public function init() + { + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + + // Ensure this option is enabled or else line endings will not always + // be detected properly for files created on a Mac with the /r line ending. + @ini_set('auto_detect_line_endings', true); + + // Disable the PCRE JIT as this caused issues with parallel running. + ini_set('pcre.jit', false); + + // Check that the standards are valid. + foreach ($this->config->standards as $standard) { + if (Util\Standards::isInstalledStandard($standard) === false) { + // They didn't select a valid coding standard, so help them + // out by letting them know which standards are installed. + $error = 'ERROR: the "'.$standard.'" coding standard is not installed. '; + ob_start(); + Util\Standards::printInstalledStandards(); + $error .= ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($error, 3); + } + } + + // Saves passing the Config object into other objects that only need + // the verbosity flag for debug output. + if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', $this->config->verbosity); + } + + // Create this class so it is autoloaded and sets up a bunch + // of PHP_CodeSniffer-specific token type constants. + $tokens = new Util\Tokens(); + + // Allow autoloading of custom files inside installed standards. + $installedStandards = Standards::getInstalledStandardDetails(); + foreach ($installedStandards as $name => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + } + + // The ruleset contains all the information about how the files + // should be checked and/or fixed. + try { + $this->ruleset = new Ruleset($this->config); + } catch (RuntimeException $e) { + $error = 'ERROR: '.$e->getMessage().PHP_EOL.PHP_EOL; + $error .= $this->config->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + }//end init() + + + /** + * Performs the run. + * + * @return int The number of errors and warnings found. + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + private function run() + { + // The class that manages all reporters for the run. + $this->reporter = new Reporter($this->config); + + // Include bootstrap files. + foreach ($this->config->bootstrap as $bootstrap) { + include $bootstrap; + } + + if ($this->config->stdin === true) { + $fileContents = $this->config->stdinContent; + if ($fileContents === null) { + $handle = fopen('php://stdin', 'r'); + stream_set_blocking($handle, true); + $fileContents = stream_get_contents($handle); + fclose($handle); + } + + $todo = new FileList($this->config, $this->ruleset); + $dummy = new DummyFile($fileContents, $this->ruleset, $this->config); + $todo->addFile($dummy->path, $dummy); + } else { + if (empty($this->config->files) === true) { + $error = 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL; + $error .= $this->config->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Creating file list... '; + } + + $todo = new FileList($this->config, $this->ruleset); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $numFiles = count($todo); + echo "DONE ($numFiles files in queue)".PHP_EOL; + } + + if ($this->config->cache === true) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Loading cache... '; + } + + Cache::load($this->ruleset, $this->config); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $size = Cache::getSize(); + echo "DONE ($size files in cache)".PHP_EOL; + } + } + }//end if + + // Turn all sniff errors into exceptions. + set_error_handler([$this, 'handleErrors']); + + // If verbosity is too high, turn off parallelism so the + // debug output is clean. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $this->config->parallel = 1; + } + + // If the PCNTL extension isn't installed, we can't fork. + if (function_exists('pcntl_fork') === false) { + $this->config->parallel = 1; + } + + $lastDir = ''; + $numFiles = count($todo); + + if ($this->config->parallel === 1) { + // Running normally. + $numProcessed = 0; + foreach ($todo as $path => $file) { + if ($file->ignored === false) { + $currDir = dirname($path); + if ($lastDir !== $currDir) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + } + + $lastDir = $currDir; + } + + $this->processFile($file); + } else if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Skipping '.basename($file->path).PHP_EOL; + } + + $numProcessed++; + $this->printProgress($file, $numFiles, $numProcessed); + } + } else { + // Batching and forking. + $childProcs = []; + $numPerBatch = ceil($numFiles / $this->config->parallel); + + for ($batch = 0; $batch < $this->config->parallel; $batch++) { + $startAt = ($batch * $numPerBatch); + if ($startAt >= $numFiles) { + break; + } + + $endAt = ($startAt + $numPerBatch); + if ($endAt > $numFiles) { + $endAt = $numFiles; + } + + $childOutFilename = tempnam(sys_get_temp_dir(), 'phpcs-child'); + $pid = pcntl_fork(); + if ($pid === -1) { + throw new RuntimeException('Failed to create child process'); + } else if ($pid !== 0) { + $childProcs[$pid] = $childOutFilename; + } else { + // Move forward to the start of the batch. + $todo->rewind(); + for ($i = 0; $i < $startAt; $i++) { + $todo->next(); + } + + // Reset the reporter to make sure only figures from this + // file batch are recorded. + $this->reporter->totalFiles = 0; + $this->reporter->totalErrors = 0; + $this->reporter->totalWarnings = 0; + $this->reporter->totalFixable = 0; + $this->reporter->totalFixed = 0; + + // Process the files. + $pathsProcessed = []; + ob_start(); + for ($i = $startAt; $i < $endAt; $i++) { + $path = $todo->key(); + $file = $todo->current(); + + if ($file->ignored === true) { + $todo->next(); + continue; + } + + $currDir = dirname($path); + if ($lastDir !== $currDir) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + } + + $lastDir = $currDir; + } + + $this->processFile($file); + + $pathsProcessed[] = $path; + $todo->next(); + }//end for + + $debugOutput = ob_get_contents(); + ob_end_clean(); + + // Write information about the run to the filesystem + // so it can be picked up by the main process. + $childOutput = [ + 'totalFiles' => $this->reporter->totalFiles, + 'totalErrors' => $this->reporter->totalErrors, + 'totalWarnings' => $this->reporter->totalWarnings, + 'totalFixable' => $this->reporter->totalFixable, + 'totalFixed' => $this->reporter->totalFixed, + ]; + + $output = '<'.'?php'."\n".' $childOutput = '; + $output .= var_export($childOutput, true); + $output .= ";\n\$debugOutput = "; + $output .= var_export($debugOutput, true); + + if ($this->config->cache === true) { + $childCache = []; + foreach ($pathsProcessed as $path) { + $childCache[$path] = Cache::get($path); + } + + $output .= ";\n\$childCache = "; + $output .= var_export($childCache, true); + } + + $output .= ";\n?".'>'; + file_put_contents($childOutFilename, $output); + exit(); + }//end if + }//end for + + $success = $this->processChildProcs($childProcs); + if ($success === false) { + throw new RuntimeException('One or more child processes failed to run'); + } + }//end if + + restore_error_handler(); + + if (PHP_CODESNIFFER_VERBOSITY === 0 + && $this->config->interactive === false + && $this->config->showProgress === true + ) { + echo PHP_EOL.PHP_EOL; + } + + if ($this->config->cache === true) { + Cache::save(); + } + + $ignoreWarnings = Config::getConfigData('ignore_warnings_on_exit'); + $ignoreErrors = Config::getConfigData('ignore_errors_on_exit'); + + $return = ($this->reporter->totalErrors + $this->reporter->totalWarnings); + if ($ignoreErrors !== null) { + $ignoreErrors = (bool) $ignoreErrors; + if ($ignoreErrors === true) { + $return -= $this->reporter->totalErrors; + } + } + + if ($ignoreWarnings !== null) { + $ignoreWarnings = (bool) $ignoreWarnings; + if ($ignoreWarnings === true) { + $return -= $this->reporter->totalWarnings; + } + } + + return $return; + + }//end run() + + + /** + * Converts all PHP errors into exceptions. + * + * This method forces a sniff to stop processing if it is not + * able to handle a specific piece of code, instead of continuing + * and potentially getting into a loop. + * + * @param int $code The level of error raised. + * @param string $message The error message. + * @param string $file The path of the file that raised the error. + * @param int $line The line number the error was raised at. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function handleErrors($code, $message, $file, $line) + { + if ((error_reporting() & $code) === 0) { + // This type of error is being muted. + return true; + } + + throw new RuntimeException("$message in $file on line $line"); + + }//end handleErrors() + + + /** + * Processes a single file, including checking and fixing. + * + * @param \PHP_CodeSniffer\Files\File $file The file to be processed. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processFile($file) + { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $startTime = microtime(true); + echo 'Processing '.basename($file->path).' '; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + try { + $file->process(); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + if (PHP_CODESNIFFER_CBF === true) { + $errors = $file->getFixableCount(); + echo " ($errors fixable violations)".PHP_EOL; + } else { + $errors = $file->getErrorCount(); + $warnings = $file->getWarningCount(); + echo " ($errors errors, $warnings warnings)".PHP_EOL; + } + } + } catch (\Exception $e) { + $error = 'An error occurred during processing; checking has been aborted. The error message was: '.$e->getMessage(); + $file->addErrorOnLine($error, 1, 'Internal.Exception'); + }//end try + + $this->reporter->cacheFileReport($file, $this->config); + + if ($this->config->interactive === true) { + /* + Running interactively. + Print the error report for the current file and then wait for user input. + */ + + // Get current violations and then clear the list to make sure + // we only print violations for a single file each time. + $numErrors = null; + while ($numErrors !== 0) { + $numErrors = ($file->getErrorCount() + $file->getWarningCount()); + if ($numErrors === 0) { + continue; + } + + $this->reporter->printReport('full'); + + echo ' to recheck, [s] to skip or [q] to quit : '; + $input = fgets(STDIN); + $input = trim($input); + + switch ($input) { + case 's': + break(2); + case 'q': + throw new DeepExitException('', 0); + default: + // Repopulate the sniffs because some of them save their state + // and only clear it when the file changes, but we are rechecking + // the same file. + $file->ruleset->populateTokenListeners(); + $file->reloadContent(); + $file->process(); + $this->reporter->cacheFileReport($file, $this->config); + break; + } + }//end while + }//end if + + // Clean up the file to save (a lot of) memory. + $file->cleanUp(); + + }//end processFile() + + + /** + * Waits for child processes to complete and cleans up after them. + * + * The reporting information returned by each child process is merged + * into the main reporter class. + * + * @param array $childProcs An array of child processes to wait for. + * + * @return bool + */ + private function processChildProcs($childProcs) + { + $numProcessed = 0; + $totalBatches = count($childProcs); + + $success = true; + + while (count($childProcs) > 0) { + $pid = pcntl_waitpid(0, $status); + if ($pid <= 0) { + continue; + } + + $out = $childProcs[$pid]; + unset($childProcs[$pid]); + if (file_exists($out) === false) { + continue; + } + + include $out; + unlink($out); + + $numProcessed++; + + if (isset($childOutput) === false) { + // The child process died, so the run has failed. + $file = new DummyFile('', $this->ruleset, $this->config); + $file->setErrorCounts(1, 0, 0, 0); + $this->printProgress($file, $totalBatches, $numProcessed); + $success = false; + continue; + } + + $this->reporter->totalFiles += $childOutput['totalFiles']; + $this->reporter->totalErrors += $childOutput['totalErrors']; + $this->reporter->totalWarnings += $childOutput['totalWarnings']; + $this->reporter->totalFixable += $childOutput['totalFixable']; + $this->reporter->totalFixed += $childOutput['totalFixed']; + + if (isset($debugOutput) === true) { + echo $debugOutput; + } + + if (isset($childCache) === true) { + foreach ($childCache as $path => $cache) { + Cache::set($path, $cache); + } + } + + // Fake a processed file so we can print progress output for the batch. + $file = new DummyFile('', $this->ruleset, $this->config); + $file->setErrorCounts( + $childOutput['totalErrors'], + $childOutput['totalWarnings'], + $childOutput['totalFixable'], + $childOutput['totalFixed'] + ); + $this->printProgress($file, $totalBatches, $numProcessed); + }//end while + + return $success; + + }//end processChildProcs() + + + /** + * Print progress information for a single processed file. + * + * @param \PHP_CodeSniffer\Files\File $file The file that was processed. + * @param int $numFiles The total number of files to process. + * @param int $numProcessed The number of files that have been processed, + * including this one. + * + * @return void + */ + public function printProgress(File $file, $numFiles, $numProcessed) + { + if (PHP_CODESNIFFER_VERBOSITY > 0 + || $this->config->showProgress === false + ) { + return; + } + + // Show progress information. + if ($file->ignored === true) { + echo 'S'; + } else { + $errors = $file->getErrorCount(); + $warnings = $file->getWarningCount(); + $fixable = $file->getFixableCount(); + $fixed = $file->getFixedCount(); + + if (PHP_CODESNIFFER_CBF === true) { + // Files with fixed errors or warnings are F (green). + // Files with unfixable errors or warnings are E (red). + // Files with no errors or warnings are . (black). + if ($fixable > 0) { + if ($this->config->colors === true) { + echo "\033[31m"; + } + + echo 'E'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else if ($fixed > 0) { + if ($this->config->colors === true) { + echo "\033[32m"; + } + + echo 'F'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else { + echo '.'; + }//end if + } else { + // Files with errors are E (red). + // Files with fixable errors are E (green). + // Files with warnings are W (yellow). + // Files with fixable warnings are W (green). + // Files with no errors or warnings are . (black). + if ($errors > 0) { + if ($this->config->colors === true) { + if ($fixable > 0) { + echo "\033[32m"; + } else { + echo "\033[31m"; + } + } + + echo 'E'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else if ($warnings > 0) { + if ($this->config->colors === true) { + if ($fixable > 0) { + echo "\033[32m"; + } else { + echo "\033[33m"; + } + } + + echo 'W'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else { + echo '.'; + }//end if + }//end if + }//end if + + $numPerLine = 60; + if ($numProcessed !== $numFiles && ($numProcessed % $numPerLine) !== 0) { + return; + } + + $percent = round(($numProcessed / $numFiles) * 100); + $padding = (strlen($numFiles) - strlen($numProcessed)); + if ($numProcessed === $numFiles + && $numFiles > $numPerLine + && ($numProcessed % $numPerLine) !== 0 + ) { + $padding += ($numPerLine - ($numFiles - (floor($numFiles / $numPerLine) * $numPerLine))); + } + + echo str_repeat(' ', $padding)." $numProcessed / $numFiles ($percent%)".PHP_EOL; + + }//end printProgress() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php new file mode 100644 index 000000000..141b9a133 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php @@ -0,0 +1,172 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractArraySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + final public function register() + { + return [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + $arrayStart = $tokens[$stackPtr]['parenthesis_opener']; + if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) { + // Incomplete array. + return; + } + + $arrayEnd = $tokens[$arrayStart]['parenthesis_closer']; + } else { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + $arrayStart = $stackPtr; + $arrayEnd = $tokens[$stackPtr]['bracket_closer']; + } + + $lastContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($arrayEnd - 1), null, true); + if ($tokens[$lastContent]['code'] === T_COMMA) { + // Last array item ends with a comma. + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no'); + } + + $indices = []; + + $current = $arrayStart; + while (($next = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), $arrayEnd, true)) !== false) { + $end = $this->getNext($phpcsFile, $next, $arrayEnd); + + if ($tokens[$end]['code'] === T_DOUBLE_ARROW) { + $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true); + $valueStart = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + + $indices[] = [ + 'index_start' => $next, + 'index_end' => $indexEnd, + 'arrow' => $end, + 'value_start' => $valueStart, + ]; + } else { + $valueStart = $next; + $indices[] = ['value_start' => $valueStart]; + } + + $current = $this->getNext($phpcsFile, $valueStart, $arrayEnd); + } + + if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) { + $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + } else { + $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + } + + }//end process() + + + /** + * Find next separator in array - either: comma or double arrow. + * + * @param File $phpcsFile The current file being checked. + * @param int $ptr The position of current token. + * @param int $arrayEnd The token that ends the array definition. + * + * @return int + */ + private function getNext(File $phpcsFile, $ptr, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + + while ($ptr < $arrayEnd) { + if (isset($tokens[$ptr]['scope_closer']) === true) { + $ptr = $tokens[$ptr]['scope_closer']; + } else if (isset($tokens[$ptr]['parenthesis_closer']) === true) { + $ptr = $tokens[$ptr]['parenthesis_closer']; + } else if (isset($tokens[$ptr]['bracket_closer']) === true) { + $ptr = $tokens[$ptr]['bracket_closer']; + } + + if ($tokens[$ptr]['code'] === T_COMMA + || $tokens[$ptr]['code'] === T_DOUBLE_ARROW + ) { + return $ptr; + } + + ++$ptr; + } + + return $ptr; + + }//end getNext() + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + abstract protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + abstract protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php new file mode 100644 index 000000000..66bc2f524 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php @@ -0,0 +1,936 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Tokenizers\PHP; +use PHP_CodeSniffer\Exceptions\RuntimeException; + +abstract class AbstractPatternSniff implements Sniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = false; + + /** + * The current file being checked. + * + * @var string + */ + protected $currFile = ''; + + /** + * The parsed patterns array. + * + * @var array + */ + private $parsedPatterns = []; + + /** + * Tokens that this sniff wishes to process outside of the patterns. + * + * @var int[] + * @see registerSupplementary() + * @see processSupplementary() + */ + private $supplementaryTokens = []; + + /** + * Positions in the stack where errors have occurred. + * + * @var array + */ + private $errorPos = []; + + + /** + * Constructs a AbstractPatternSniff. + * + * @param boolean $ignoreComments If true, comments will be ignored. + */ + public function __construct($ignoreComments=null) + { + // This is here for backwards compatibility. + if ($ignoreComments !== null) { + $this->ignoreComments = $ignoreComments; + } + + $this->supplementaryTokens = $this->registerSupplementary(); + + }//end __construct() + + + /** + * Registers the tokens to listen to. + * + * Classes extending AbstractPatternTest should implement the + * getPatterns() method to register the patterns they wish to test. + * + * @return int[] + * @see process() + */ + final public function register() + { + $listenTypes = []; + $patterns = $this->getPatterns(); + + foreach ($patterns as $pattern) { + $parsedPattern = $this->parse($pattern); + + // Find a token position in the pattern that we can use + // for a listener token. + $pos = $this->getListenerTokenPos($parsedPattern); + $tokenType = $parsedPattern[$pos]['token']; + $listenTypes[] = $tokenType; + + $patternArray = [ + 'listen_pos' => $pos, + 'pattern' => $parsedPattern, + 'pattern_code' => $pattern, + ]; + + if (isset($this->parsedPatterns[$tokenType]) === false) { + $this->parsedPatterns[$tokenType] = []; + } + + $this->parsedPatterns[$tokenType][] = $patternArray; + }//end foreach + + return array_unique(array_merge($listenTypes, $this->supplementaryTokens)); + + }//end register() + + + /** + * Returns the token types that the specified pattern is checking for. + * + * Returned array is in the format: + * + * array( + * T_WHITESPACE => 0, // 0 is the position where the T_WHITESPACE token + * // should occur in the pattern. + * ); + * + * + * @param array $pattern The parsed pattern to find the acquire the token + * types from. + * + * @return array + */ + private function getPatternTokenTypes($pattern) + { + $tokenTypes = []; + foreach ($pattern as $pos => $patternInfo) { + if ($patternInfo['type'] === 'token') { + if (isset($tokenTypes[$patternInfo['token']]) === false) { + $tokenTypes[$patternInfo['token']] = $pos; + } + } + } + + return $tokenTypes; + + }//end getPatternTokenTypes() + + + /** + * Returns the position in the pattern that this test should register as + * a listener for the pattern. + * + * @param array $pattern The pattern to acquire the listener for. + * + * @return int The position in the pattern that this test should register + * as the listener. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If we could not determine a token to listen for. + */ + private function getListenerTokenPos($pattern) + { + $tokenTypes = $this->getPatternTokenTypes($pattern); + $tokenCodes = array_keys($tokenTypes); + $token = Tokens::getHighestWeightedToken($tokenCodes); + + // If we could not get a token. + if ($token === false) { + $error = 'Could not determine a token to listen for'; + throw new RuntimeException($error); + } + + return $tokenTypes[$token]; + + }//end getListenerTokenPos() + + + /** + * Processes the test. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ + final public function process(File $phpcsFile, $stackPtr) + { + $file = $phpcsFile->getFilename(); + if ($this->currFile !== $file) { + // We have changed files, so clean up. + $this->errorPos = []; + $this->currFile = $file; + } + + $tokens = $phpcsFile->getTokens(); + + if (in_array($tokens[$stackPtr]['code'], $this->supplementaryTokens, true) === true) { + $this->processSupplementary($phpcsFile, $stackPtr); + } + + $type = $tokens[$stackPtr]['code']; + + // If the type is not set, then it must have been a token registered + // with registerSupplementary(). + if (isset($this->parsedPatterns[$type]) === false) { + return; + } + + $allErrors = []; + + // Loop over each pattern that is listening to the current token type + // that we are processing. + foreach ($this->parsedPatterns[$type] as $patternInfo) { + // If processPattern returns false, then the pattern that we are + // checking the code with must not be designed to check that code. + $errors = $this->processPattern($patternInfo, $phpcsFile, $stackPtr); + if ($errors === false) { + // The pattern didn't match. + continue; + } else if (empty($errors) === true) { + // The pattern matched, but there were no errors. + break; + } + + foreach ($errors as $stackPtr => $error) { + if (isset($this->errorPos[$stackPtr]) === false) { + $this->errorPos[$stackPtr] = true; + $allErrors[$stackPtr] = $error; + } + } + } + + foreach ($allErrors as $stackPtr => $error) { + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + + /** + * Processes the pattern and verifies the code at $stackPtr. + * + * @param array $patternInfo Information about the pattern used + * for checking, which includes are + * parsed token representation of the + * pattern. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack where + * the listening token type was found. + * + * @return array + */ + protected function processPattern($patternInfo, File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $pattern = $patternInfo['pattern']; + $patternCode = $patternInfo['pattern_code']; + $errors = []; + $found = ''; + + $ignoreTokens = [T_WHITESPACE => T_WHITESPACE]; + if ($this->ignoreComments === true) { + $ignoreTokens += Tokens::$commentTokens; + } + + $origStackPtr = $stackPtr; + $hasError = false; + + if ($patternInfo['listen_pos'] > 0) { + $stackPtr--; + + for ($i = ($patternInfo['listen_pos'] - 1); $i >= 0; $i--) { + if ($pattern[$i]['type'] === 'token') { + if ($pattern[$i]['token'] === T_WHITESPACE) { + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + $found = $tokens[$stackPtr]['content'].$found; + } + + // Only check the size of the whitespace if this is not + // the first token. We don't care about the size of + // leading whitespace, just that there is some. + if ($i !== 0) { + if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) { + $hasError = true; + } + } + } else { + // Check to see if this important token is the same as the + // previous important token in the pattern. If it is not, + // then the pattern cannot be for this piece of code. + $prev = $phpcsFile->findPrevious( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($prev === false + || $tokens[$prev]['code'] !== $pattern[$i]['token'] + ) { + return false; + } + + // If we skipped past some whitespace tokens, then add them + // to the found string. + $tokenContent = $phpcsFile->getTokensAsString( + ($prev + 1), + ($stackPtr - $prev - 1) + ); + + $found = $tokens[$prev]['content'].$tokenContent.$found; + + if (isset($pattern[($i - 1)]) === true + && $pattern[($i - 1)]['type'] === 'skip' + ) { + $stackPtr = $prev; + } else { + $stackPtr = ($prev - 1); + } + }//end if + } else if ($pattern[$i]['type'] === 'skip') { + // Skip to next piece of relevant code. + if ($pattern[$i]['to'] === 'parenthesis_closer') { + $to = 'parenthesis_opener'; + } else { + $to = 'scope_opener'; + } + + // Find the previous opener. + $next = $phpcsFile->findPrevious( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next === false || isset($tokens[$next][$to]) === false) { + // If there was not opener, then we must be + // using the wrong pattern. + return false; + } + + if ($to === 'parenthesis_opener') { + $found = '{'.$found; + } else { + $found = '('.$found; + } + + $found = '...'.$found; + + // Skip to the opening token. + $stackPtr = ($tokens[$next][$to] - 1); + } else if ($pattern[$i]['type'] === 'string') { + $found = 'abc'; + } else if ($pattern[$i]['type'] === 'newline') { + if ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true + ) { + $startComment = $phpcsFile->findPrevious( + Tokens::$commentTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$startComment]['line'] !== $tokens[($startComment + 1)]['line']) { + $startComment++; + } + + $tokenContent = $phpcsFile->getTokensAsString( + $startComment, + ($stackPtr - $startComment + 1) + ); + + $found = $tokenContent.$found; + $stackPtr = ($startComment - 1); + } + + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) { + $found = $tokens[$stackPtr]['content'].$found; + + // This may just be an indent that comes after a newline + // so check the token before to make sure. If it is a newline, we + // can ignore the error here. + if (($tokens[($stackPtr - 1)]['content'] !== $phpcsFile->eolChar) + && ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[($stackPtr - 1)]['code']]) === false) + ) { + $hasError = true; + } else { + $stackPtr--; + } + } else { + $found = 'EOL'.$found; + } + } else { + $found = $tokens[$stackPtr]['content'].$found; + $hasError = true; + }//end if + + if ($hasError === false && $pattern[($i - 1)]['type'] !== 'newline') { + // Make sure they only have 1 newline. + $prev = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) { + $hasError = true; + } + } + }//end if + }//end for + }//end if + + $stackPtr = $origStackPtr; + $lastAddedStackPtr = null; + $patternLen = count($pattern); + + for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) { + if (isset($tokens[$stackPtr]) === false) { + break; + } + + if ($pattern[$i]['type'] === 'token') { + if ($pattern[$i]['token'] === T_WHITESPACE) { + if ($this->ignoreComments === true) { + // If we are ignoring comments, check to see if this current + // token is a comment. If so skip it. + if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) { + continue; + } + + // If the next token is a comment, the we need to skip the + // current token as we should allow a space before a + // comment for readability. + if (isset($tokens[($stackPtr + 1)]) === true + && isset(Tokens::$commentTokens[$tokens[($stackPtr + 1)]['code']]) === true + ) { + continue; + } + } + + $tokenContent = ''; + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + if (isset($pattern[($i + 1)]) === false) { + // This is the last token in the pattern, so just compare + // the next token of content. + $tokenContent = $tokens[$stackPtr]['content']; + } else { + // Get all the whitespace to the next token. + $next = $phpcsFile->findNext( + Tokens::$emptyTokens, + $stackPtr, + null, + true + ); + + $tokenContent = $phpcsFile->getTokensAsString( + $stackPtr, + ($next - $stackPtr) + ); + + $lastAddedStackPtr = $stackPtr; + $stackPtr = $next; + }//end if + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $tokenContent; + } + } else { + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $tokens[$stackPtr]['content']; + $lastAddedStackPtr = $stackPtr; + } + }//end if + + if (isset($pattern[($i + 1)]) === true + && $pattern[($i + 1)]['type'] === 'skip' + ) { + // The next token is a skip token, so we just need to make + // sure the whitespace we found has *at least* the + // whitespace required. + if (strpos($tokenContent, $pattern[$i]['value']) !== 0) { + $hasError = true; + } + } else { + if ($tokenContent !== $pattern[$i]['value']) { + $hasError = true; + } + } + } else { + // Check to see if this important token is the same as the + // next important token in the pattern. If it is not, then + // the pattern cannot be for this piece of code. + $next = $phpcsFile->findNext( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next === false + || $tokens[$next]['code'] !== $pattern[$i]['token'] + ) { + // The next important token did not match the pattern. + return false; + } + + if ($lastAddedStackPtr !== null) { + if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) + && isset($tokens[$next]['scope_condition']) === true + && $tokens[$next]['scope_condition'] > $lastAddedStackPtr + ) { + // This is a brace, but the owner of it is after the current + // token, which means it does not belong to any token in + // our pattern. This means the pattern is not for us. + return false; + } + + if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS + || $tokens[$next]['code'] === T_CLOSE_PARENTHESIS) + && isset($tokens[$next]['parenthesis_owner']) === true + && $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr + ) { + // This is a bracket, but the owner of it is after the current + // token, which means it does not belong to any token in + // our pattern. This means the pattern is not for us. + return false; + } + }//end if + + // If we skipped past some whitespace tokens, then add them + // to the found string. + if (($next - $stackPtr) > 0) { + $hasComment = false; + for ($j = $stackPtr; $j < $next; $j++) { + $found .= $tokens[$j]['content']; + if (isset(Tokens::$commentTokens[$tokens[$j]['code']]) === true) { + $hasComment = true; + } + } + + // If we are not ignoring comments, this additional + // whitespace or comment is not allowed. If we are + // ignoring comments, there needs to be at least one + // comment for this to be allowed. + if ($this->ignoreComments === false + || ($this->ignoreComments === true + && $hasComment === false) + ) { + $hasError = true; + } + + // Even when ignoring comments, we are not allowed to include + // newlines without the pattern specifying them, so + // everything should be on the same line. + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $hasError = true; + } + }//end if + + if ($next !== $lastAddedStackPtr) { + $found .= $tokens[$next]['content']; + $lastAddedStackPtr = $next; + } + + if (isset($pattern[($i + 1)]) === true + && $pattern[($i + 1)]['type'] === 'skip' + ) { + $stackPtr = $next; + } else { + $stackPtr = ($next + 1); + } + }//end if + } else if ($pattern[$i]['type'] === 'skip') { + if ($pattern[$i]['to'] === 'unknown') { + $next = $phpcsFile->findNext( + $pattern[($i + 1)]['token'], + $stackPtr + ); + + if ($next === false) { + // Couldn't find the next token, so we must + // be using the wrong pattern. + return false; + } + + $found .= '...'; + $stackPtr = $next; + } else { + // Find the previous opener. + $next = $phpcsFile->findPrevious( + Tokens::$blockOpeners, + $stackPtr + ); + + if ($next === false + || isset($tokens[$next][$pattern[$i]['to']]) === false + ) { + // If there was not opener, then we must + // be using the wrong pattern. + return false; + } + + $found .= '...'; + if ($pattern[$i]['to'] === 'parenthesis_closer') { + $found .= ')'; + } else { + $found .= '}'; + } + + // Skip to the closing token. + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + }//end if + } else if ($pattern[$i]['type'] === 'string') { + if ($tokens[$stackPtr]['code'] !== T_STRING) { + $hasError = true; + } + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= 'abc'; + $lastAddedStackPtr = $stackPtr; + } + + $stackPtr++; + } else if ($pattern[$i]['type'] === 'newline') { + // Find the next token that contains a newline character. + $newline = 0; + for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) { + if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) { + $newline = $j; + break; + } + } + + if ($newline === 0) { + // We didn't find a newline character in the rest of the file. + $next = ($phpcsFile->numTokens - 1); + $hasError = true; + } else { + if ($this->ignoreComments === false) { + // The newline character cannot be part of a comment. + if (isset(Tokens::$commentTokens[$tokens[$newline]['code']]) === true) { + $hasError = true; + } + } + + if ($newline === $stackPtr) { + $next = ($stackPtr + 1); + } else { + // Check that there were no significant tokens that we + // skipped over to find our newline character. + $next = $phpcsFile->findNext( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next < $newline) { + // We skipped a non-ignored token. + $hasError = true; + } else { + $next = ($newline + 1); + } + } + }//end if + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $phpcsFile->getTokensAsString( + $stackPtr, + ($next - $stackPtr) + ); + + $lastAddedStackPtr = ($next - 1); + } + + $stackPtr = $next; + }//end if + }//end for + + if ($hasError === true) { + $error = $this->prepareError($found, $patternCode); + $errors[$origStackPtr] = $error; + } + + return $errors; + + }//end processPattern() + + + /** + * Prepares an error for the specified patternCode. + * + * @param string $found The actual found string in the code. + * @param string $patternCode The expected pattern code. + * + * @return string The error message. + */ + protected function prepareError($found, $patternCode) + { + $found = str_replace("\r\n", '\n', $found); + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\n', $found); + $found = str_replace("\t", '\t', $found); + $found = str_replace('EOL', '\n', $found); + $expected = str_replace('EOL', '\n', $patternCode); + + $error = "Expected \"$expected\"; found \"$found\""; + + return $error; + + }//end prepareError() + + + /** + * Returns the patterns that should be checked. + * + * @return string[] + */ + abstract protected function getPatterns(); + + + /** + * Registers any supplementary tokens that this test might wish to process. + * + * A sniff may wish to register supplementary tests when it wishes to group + * an arbitrary validation that cannot be performed using a pattern, with + * other pattern tests. + * + * @return int[] + * @see processSupplementary() + */ + protected function registerSupplementary() + { + return []; + + }//end registerSupplementary() + + + /** + * Processes any tokens registered with registerSupplementary(). + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where to + * process the skip. + * @param int $stackPtr The position in the tokens stack to + * process. + * + * @return void + * @see registerSupplementary() + */ + protected function processSupplementary(File $phpcsFile, $stackPtr) + { + + }//end processSupplementary() + + + /** + * Parses a pattern string into an array of pattern steps. + * + * @param string $pattern The pattern to parse. + * + * @return array The parsed pattern array. + * @see createSkipPattern() + * @see createTokenPattern() + */ + private function parse($pattern) + { + $patterns = []; + $length = strlen($pattern); + $lastToken = 0; + $firstToken = 0; + + for ($i = 0; $i < $length; $i++) { + $specialPattern = false; + $isLastChar = ($i === ($length - 1)); + $oldFirstToken = $firstToken; + + if (substr($pattern, $i, 3) === '...') { + // It's a skip pattern. The skip pattern requires the + // content of the token in the "from" position and the token + // to skip to. + $specialPattern = $this->createSkipPattern($pattern, ($i - 1)); + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + + if ($specialPattern['to'] !== 'unknown') { + $firstToken++; + } + } else if (substr($pattern, $i, 3) === 'abc') { + $specialPattern = ['type' => 'string']; + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + } else if (substr($pattern, $i, 3) === 'EOL') { + $specialPattern = ['type' => 'newline']; + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + }//end if + + if ($specialPattern !== false || $isLastChar === true) { + // If we are at the end of the string, don't worry about a limit. + if ($isLastChar === true) { + // Get the string from the end of the last skip pattern, if any, + // to the end of the pattern string. + $str = substr($pattern, $oldFirstToken); + } else { + // Get the string from the end of the last special pattern, + // if any, to the start of this special pattern. + if ($lastToken === 0) { + // Note that if the last special token was zero characters ago, + // there will be nothing to process so we can skip this bit. + // This happens if you have something like: EOL... in your pattern. + $str = ''; + } else { + $str = substr($pattern, $oldFirstToken, $lastToken); + } + } + + if ($str !== '') { + $tokenPatterns = $this->createTokenPattern($str); + foreach ($tokenPatterns as $tokenPattern) { + $patterns[] = $tokenPattern; + } + } + + // Make sure we don't skip the last token. + if ($isLastChar === false && $i === ($length - 1)) { + $i--; + } + }//end if + + // Add the skip pattern *after* we have processed + // all the tokens from the end of the last skip pattern + // to the start of this skip pattern. + if ($specialPattern !== false) { + $patterns[] = $specialPattern; + } + }//end for + + return $patterns; + + }//end parse() + + + /** + * Creates a skip pattern. + * + * @param string $pattern The pattern being parsed. + * @param string $from The token content that the skip pattern starts from. + * + * @return array The pattern step. + * @see createTokenPattern() + * @see parse() + */ + private function createSkipPattern($pattern, $from) + { + $skip = ['type' => 'skip']; + + $nestedParenthesis = 0; + $nestedBraces = 0; + for ($start = $from; $start >= 0; $start--) { + switch ($pattern[$start]) { + case '(': + if ($nestedParenthesis === 0) { + $skip['to'] = 'parenthesis_closer'; + } + + $nestedParenthesis--; + break; + case '{': + if ($nestedBraces === 0) { + $skip['to'] = 'scope_closer'; + } + + $nestedBraces--; + break; + case '}': + $nestedBraces++; + break; + case ')': + $nestedParenthesis++; + break; + }//end switch + + if (isset($skip['to']) === true) { + break; + } + }//end for + + if (isset($skip['to']) === false) { + $skip['to'] = 'unknown'; + } + + return $skip; + + }//end createSkipPattern() + + + /** + * Creates a token pattern. + * + * @param string $str The tokens string that the pattern should match. + * + * @return array The pattern step. + * @see createSkipPattern() + * @see parse() + */ + private function createTokenPattern($str) + { + // Don't add a space after the closing php tag as it will add a new + // whitespace token. + $tokenizer = new PHP('', null); + + // Remove the getTokens(); + $tokens = array_slice($tokens, 1, (count($tokens) - 2)); + + $patterns = []; + foreach ($tokens as $patternInfo) { + $patterns[] = [ + 'type' => 'token', + 'token' => $patternInfo['code'], + 'value' => $patternInfo['content'], + ]; + } + + return $patterns; + + }//end createTokenPattern() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php new file mode 100644 index 000000000..70d8720a1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php @@ -0,0 +1,191 @@ + + * class ClassScopeTest extends PHP_CodeSniffer_Standards_AbstractScopeSniff + * { + * public function __construct() + * { + * parent::__construct(array(T_CLASS), array(T_FUNCTION)); + * } + * + * protected function processTokenWithinScope(\PHP_CodeSniffer\Files\File $phpcsFile, $stackPtr, $currScope) + * { + * $className = $phpcsFile->getDeclarationName($currScope); + * echo 'encountered a method within class '.$className; + * } + * } + * + * + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Exceptions\RuntimeException; + +abstract class AbstractScopeSniff implements Sniff +{ + + /** + * The token types that this test wishes to listen to within the scope. + * + * @var array + */ + private $tokens = []; + + /** + * The type of scope opener tokens that this test wishes to listen to. + * + * @var string + */ + private $scopeTokens = []; + + /** + * True if this test should fire on tokens outside of the scope. + * + * @var boolean + */ + private $listenOutside = false; + + + /** + * Constructs a new AbstractScopeTest. + * + * @param array $scopeTokens The type of scope the test wishes to listen to. + * @param array $tokens The tokens that the test wishes to listen to + * within the scope. + * @param boolean $listenOutside If true this test will also alert the + * extending class when a token is found outside + * the scope, by calling the + * processTokenOutsideScope method. + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified tokens arrays are empty + * or invalid. + */ + public function __construct( + array $scopeTokens, + array $tokens, + $listenOutside=false + ) { + if (empty($scopeTokens) === true) { + $error = 'The scope tokens list cannot be empty'; + throw new RuntimeException($error); + } + + if (empty($tokens) === true) { + $error = 'The tokens list cannot be empty'; + throw new RuntimeException($error); + } + + $invalidScopeTokens = array_intersect($scopeTokens, $tokens); + if (empty($invalidScopeTokens) === false) { + $invalid = implode(', ', $invalidScopeTokens); + $error = "Scope tokens [$invalid] can't be in the tokens array"; + throw new RuntimeException($error); + } + + $this->listenOutside = $listenOutside; + $this->scopeTokens = array_flip($scopeTokens); + $this->tokens = $tokens; + + }//end __construct() + + + /** + * The method that is called to register the tokens this test wishes to + * listen to. + * + * DO NOT OVERRIDE THIS METHOD. Use the constructor of this class to register + * for the desired tokens and scope. + * + * @return int[] + * @see __constructor() + */ + final public function register() + { + return $this->tokens; + + }//end register() + + + /** + * Processes the tokens that this test is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + * @see processTokenWithinScope() + */ + final public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $foundScope = false; + $skipTokens = []; + foreach ($tokens[$stackPtr]['conditions'] as $scope => $code) { + if (isset($this->scopeTokens[$code]) === true) { + $skipTokens[] = $this->processTokenWithinScope($phpcsFile, $stackPtr, $scope); + $foundScope = true; + } + } + + if ($this->listenOutside === true && $foundScope === false) { + $skipTokens[] = $this->processTokenOutsideScope($phpcsFile, $stackPtr); + } + + if (empty($skipTokens) === false) { + return min($skipTokens); + } + + return; + + }//end process() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * @param int $currScope The position in the tokens array that + * opened the scope that this test is + * listening for. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope); + + + /** + * Processes a token that is found outside the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return (count($tokens) + 1) to skip + * the rest of the file. + */ + abstract protected function processTokenOutsideScope(File $phpcsFile, $stackPtr); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php new file mode 100644 index 000000000..5dc8ba556 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php @@ -0,0 +1,230 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractVariableSniff extends AbstractScopeSniff +{ + + /** + * List of PHP Reserved variables. + * + * Used by various naming convention sniffs. + * + * @var array + */ + protected $phpReservedVars = [ + '_SERVER' => true, + '_GET' => true, + '_POST' => true, + '_REQUEST' => true, + '_SESSION' => true, + '_ENV' => true, + '_COOKIE' => true, + '_FILES' => true, + 'GLOBALS' => true, + 'http_response_header' => true, + 'HTTP_RAW_POST_DATA' => true, + 'php_errormsg' => true, + ]; + + + /** + * Constructs an AbstractVariableTest. + */ + public function __construct() + { + $scopes = Tokens::$ooScopeTokens; + + $listen = [ + T_VARIABLE, + T_DOUBLE_QUOTED_STRING, + T_HEREDOC, + ]; + + parent::__construct($scopes, $listen, true); + + }//end __construct() + + + /** + * Processes the token in the specified PHP_CodeSniffer\Files\File. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + final protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING + || $tokens[$stackPtr]['code'] === T_HEREDOC + ) { + // Check to see if this string has a variable in it. + $pattern = '|(?processVariableInString($phpcsFile, $stackPtr); + } + + return; + } + + // If this token is nested inside a function at a deeper + // level than the current OO scope that was found, it's a normal + // variable and not a member var. + $conditions = array_reverse($tokens[$stackPtr]['conditions'], true); + $inFunction = false; + foreach ($conditions as $scope => $code) { + if (isset(Tokens::$ooScopeTokens[$code]) === true) { + break; + } + + if ($code === T_FUNCTION || $code === T_CLOSURE) { + $inFunction = true; + } + } + + if ($scope !== $currScope) { + // We found a closer scope to this token, so ignore + // this particular time through the sniff. We will process + // this token when this closer scope is found to avoid + // duplicate checks. + return; + } + + // Just make sure this isn't a variable in a function declaration. + if ($inFunction === false && isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === false) { + // Check if this is a USE statement for a closure. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true); + if ($tokens[$prev]['code'] === T_USE) { + $inFunction = true; + break; + } + + continue; + } + + $owner = $tokens[$opener]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FUNCTION + || $tokens[$owner]['code'] === T_CLOSURE + ) { + $inFunction = true; + break; + } + } + }//end if + + if ($inFunction === true) { + return $this->processVariable($phpcsFile, $stackPtr); + } else { + return $this->processMemberVar($phpcsFile, $stackPtr); + } + + }//end processTokenWithinScope() + + + /** + * Processes the token outside the scope in the file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + final protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + // These variables are not member vars. + if ($tokens[$stackPtr]['code'] === T_VARIABLE) { + return $this->processVariable($phpcsFile, $stackPtr); + } else if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING + || $tokens[$stackPtr]['code'] === T_HEREDOC + ) { + // Check to see if this string has a variable in it. + $pattern = '|(?processVariableInString($phpcsFile, $stackPtr); + } + } + + }//end processTokenOutsideScope() + + + /** + * Called to process class member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processMemberVar(File $phpcsFile, $stackPtr); + + + /** + * Called to process normal member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processVariable(File $phpcsFile, $stackPtr); + + + /** + * Called to process variables found in double quoted strings or heredocs. + * + * Note that there may be more than one variable in the string, which will + * result only in one call for the string or one call per line for heredocs. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return ($phpcsFile->numTokens + 1) to skip + * the rest of the file. + */ + abstract protected function processVariableInString(File $phpcsFile, $stackPtr); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/Sniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/Sniff.php new file mode 100644 index 000000000..3f0fb6a1c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Sniffs/Sniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; + +interface Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * An example return value for a sniff that wants to listen for whitespace + * and any comments would be: + * + * + * return array( + * T_WHITESPACE, + * T_DOC_COMMENT, + * T_COMMENT, + * ); + * + * + * @return mixed[] + * @see Tokens.php + */ + public function register(); + + + /** + * Called when one of the token types that this sniff is listening for + * is found. + * + * The stackPtr variable indicates where in the stack the token was found. + * A sniff can acquire information about this token, along with all the other + * tokens within the stack by first acquiring the token stack: + * + * + * $tokens = $phpcsFile->getTokens(); + * echo 'Encountered a '.$tokens[$stackPtr]['type'].' token'; + * echo 'token information: '; + * print_r($tokens[$stackPtr]); + * + * + * If the sniff discovers an anomaly in the code, they can raise an error + * by calling addError() on the \PHP_CodeSniffer\Files\File object, specifying an error + * message and the position of the offending token: + * + * + * $phpcsFile->addError('Encountered an error', $stackPtr); + * + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token was found. + * @param int $stackPtr The position in the PHP_CodeSniffer + * file's token stack where the token + * was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return (count($tokens) + 1) to skip + * the rest of the file. + */ + public function process(File $phpcsFile, $stackPtr); + + +}//end interface diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml new file mode 100644 index 000000000..21b0d27d2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml @@ -0,0 +1,23 @@ + + + + + + + [ + 'foo' => 'bar', +]; + ]]> + + + array( + 'foo' => 'bar', +); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml new file mode 100644 index 000000000..f24767ca5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml @@ -0,0 +1,23 @@ + + + + + + + array( + 'foo' => 'bar', +); + ]]> + + + [ + 'foo' => 'bar', +]; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml new file mode 100644 index 000000000..4b0ec96d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml @@ -0,0 +1,27 @@ + + + + + + + Foo +{ +} + ]]> + + + Foo +{ +} + +class Foo +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml new file mode 100644 index 000000000..6226a3fff --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml @@ -0,0 +1,28 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + // Start of class. +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml new file mode 100644 index 000000000..9961ea054 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $test === 'abc') { + // Code. +} + ]]> + + + $test = 'abc') { + // Code. +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml new file mode 100644 index 000000000..c400d75e2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + // do nothing +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml new file mode 100644 index 000000000..06f0b7a5b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $i = 0; $i < 10; $i++) { + echo "{$i}\n"; +} + ]]> + + + ;$test;) { + $test = doSomething(); +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml new file mode 100644 index 000000000..f40d94bb1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml @@ -0,0 +1,24 @@ + + + + + + + $end = count($foo); +for ($i = 0; $i < $end; $i++) { + echo $foo[$i]."\n"; +} + ]]> + + + count($foo); $i++) { + echo $foo[$i]."\n"; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml new file mode 100644 index 000000000..50f078288 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $i++) { + for ($j = 0; $j < 10; $j++) { + } +} + ]]> + + + $i++) { + for ($j = 0; $j < 10; $i++) { + } +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml new file mode 100644 index 000000000..b2eaabe79 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $test) { + $var = 1; +} + ]]> + + + true) { + $var = 1; +} + ]]> + + + + + $test) { + $var = 1; +} + ]]> + + + false) { + $var = 1; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml new file mode 100644 index 000000000..893674077 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml @@ -0,0 +1,29 @@ + + + + + + + + + + final function bar() + { + } +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml new file mode 100644 index 000000000..181dff4ee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $a + $b + $c; +} + ]]> + + + $a + $b; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml new file mode 100644 index 000000000..ba8bd7e42 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml @@ -0,0 +1,32 @@ + + + + + + + $this->doSomethingElse(); + } +} + ]]> + + + parent::bar(); + } +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml new file mode 100644 index 000000000..174c6b0a8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml @@ -0,0 +1,25 @@ + + + + + + + Handle strange case +if ($test) { + $var = 1; +} + ]]> + + + FIXME: This needs to be fixed! +if ($test) { + $var = 1; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml new file mode 100644 index 000000000..c9c4fc061 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml @@ -0,0 +1,25 @@ + + + + + + + Handle strange case +if ($test) { + $var = 1; +} + ]]> + + + TODO: This needs to be fixed! +if ($test) { + $var = 1; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml new file mode 100644 index 000000000..570e4192b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + { + $var = 1; +} + ]]> + + + { + $var = 1; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml new file mode 100644 index 000000000..06ae14b76 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml @@ -0,0 +1,22 @@ + + + + + + + { + $var = 1; +} + ]]> + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml new file mode 100644 index 000000000..b57a97068 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml @@ -0,0 +1,19 @@ + + + + + + + %; } + ]]> + + + %; } + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml new file mode 100644 index 000000000..9df9aec48 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ]; + ]]> + + + ,]; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml new file mode 100644 index 000000000..7525e9e6b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml @@ -0,0 +1,19 @@ + + + + + + + var foo = 5; + ]]> + + + foo = 5; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml new file mode 100644 index 000000000..88591f925 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml new file mode 100644 index 000000000..aa757edc6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml new file mode 100644 index 000000000..227d5621a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml new file mode 100644 index 000000000..6114f24c5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml new file mode 100644 index 000000000..3fbf5024d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml @@ -0,0 +1,24 @@ + + + + + + + + + + some string here + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml new file mode 100644 index 000000000..4554d0f38 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml new file mode 100644 index 000000000..31342e3c9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml new file mode 100644 index 000000000..a1be34cb0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml new file mode 100644 index 000000000..7b5857633 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + class Foo +{ +} + ]]> + + + class Foo +{ +} + +class Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml new file mode 100644 index 000000000..de975319a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + interface Foo +{ +} + ]]> + + + interface Foo +{ +} + +interface Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml new file mode 100644 index 000000000..4d957e701 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + trait Foo +{ +} + ]]> + + + trait Foo +{ +} + +class Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml new file mode 100644 index 000000000..58a6482f1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + trait Foo +{ +} + ]]> + + + trait Foo +{ +} + +trait Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml new file mode 100644 index 000000000..f0d4490c3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml new file mode 100644 index 000000000..4c33d763d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml @@ -0,0 +1,56 @@ + + + + + + + = (1 + 2); +$veryLongVarName = 'string'; +$var = foo($bar, $baz); + ]]> + + + = (1 + 2); +$veryLongVarName = 'string'; +$var = foo($bar, $baz); + ]]> + + + + + + + + += 1; +$veryLongVarName = 1; + ]]> + + + += 1; +$veryLongVarName = 1; + ]]> + + + + + = 1; +$veryLongVarName -= 1; + ]]> + + + = 1; +$veryLongVarName -= 1; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml new file mode 100644 index 000000000..042e4f803 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + 1; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml new file mode 100644 index 000000000..75eba77cb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml @@ -0,0 +1,19 @@ + + + + + + + 1; + ]]> + + + 1; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml new file mode 100644 index 000000000..dd3e77311 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $someVar || ! $x instanceOf stdClass) {}; + ]]> + + + $someVar || !$x instanceOf stdClass) {}; + ]]> + + + $someVar || ! + $x instanceOf stdClass) {}; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml new file mode 100644 index 000000000..738998d43 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml @@ -0,0 +1,31 @@ + + + + + + + &$bar) +{ + $bar++; +} + +$baz = 1; +foo($baz); + ]]> + + + &$baz); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml new file mode 100644 index 000000000..9809844d8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $baz) +{ +} + ]]> + + + $baz) +{ +} + ]]> + + + + + = true) +{ +} + ]]> + + + =true) +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml new file mode 100644 index 000000000..414dc289e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml @@ -0,0 +1,24 @@ + + + + + + + { + ... +} + ]]> + + + { + ... +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml new file mode 100644 index 000000000..84c2bdd86 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml @@ -0,0 +1,24 @@ + + + + + + + { + ... +} + ]]> + + + { + ... +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml new file mode 100644 index 000000000..a928e7db1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml new file mode 100644 index 000000000..f66cd92c9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml new file mode 100644 index 000000000..c30d26e9d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + AbstractBar +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml new file mode 100644 index 000000000..f5345b712 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + doSomething() +{ +} + ]]> + + + do_something() +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml new file mode 100644 index 000000000..9dfc175ff --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + __construct() + { + } +} + ]]> + + + Foo() + { + } +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml new file mode 100644 index 000000000..0aa0c76e4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + BarInterface +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml new file mode 100644 index 000000000..711867e45 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + BarTrait +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml new file mode 100644 index 000000000..6ef61b93c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + FOO_CONSTANT', 'foo'); + +class FooClass +{ + const FOO_CONSTANT = 'foo'; +} + ]]> + + + Foo_Constant', 'foo'); + +class FooClass +{ + const foo_constant = 'foo'; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml new file mode 100644 index 000000000..4ebd67704 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml new file mode 100644 index 000000000..df5a0eba4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + + + + Beginning content + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml new file mode 100644 index 000000000..09afb2d75 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + +echo 'Foo'; +?> + ]]> + + + +echo 'Foo'; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml new file mode 100644 index 000000000..33b803a75 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + explode('a', $bar); + ]]> + + + split('a', $bar); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml new file mode 100644 index 000000000..bdfd5dc16 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml @@ -0,0 +1,7 @@ + + + to delimit PHP code, do not use the ASP <% %> style tags nor the tags. This is the most portable way to include PHP code on differing operating systems and setups. + ]]> + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml new file mode 100644 index 000000000..f94769427 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml new file mode 100644 index 000000000..8086ea271 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml @@ -0,0 +1,7 @@ + + + to delimit PHP code, not the shorthand. This is the most portable way to include PHP code on differing operating systems and setups. + ]]> + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml new file mode 100644 index 000000000..83bceef40 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml new file mode 100644 index 000000000..c0f18b557 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + count($bar); + ]]> + + + sizeof($bar); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml new file mode 100644 index 000000000..7dc30c10d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml @@ -0,0 +1,23 @@ + + + true, false and null constants must always be lowercase. + ]]> + + + + false || $var === null) { + $var = true; +} + ]]> + + + FALSE || $var === NULL) { + $var = TRUE; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml new file mode 100644 index 000000000..965742d94 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml @@ -0,0 +1,19 @@ + + + + + + + array(); + ]]> + + + Array(); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml new file mode 100644 index 000000000..f38df3af5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml @@ -0,0 +1,38 @@ + + + + + + + + + + Int $foo) : STRING { +} + ]]> + + + + + + + + + + + (BOOL) $isValid; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml new file mode 100644 index 000000000..df6988794 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + isset($foo) && $foo) { + echo "Hello\n"; +} + ]]> + + + @$foo) { + echo "Hello\n"; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml new file mode 100644 index 000000000..e74005ad1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml @@ -0,0 +1,23 @@ + + + + + + + PHP_SAPI === 'cli') { + echo "Hello, CLI user."; +} + ]]> + + + php_sapi_name() === 'cli') { + echo "Hello, CLI user."; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml new file mode 100644 index 000000000..1f337f77e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml @@ -0,0 +1,23 @@ + + + true, false and null constants must always be uppercase. + ]]> + + + + FALSE || $var === NULL) { + $var = TRUE; +} + ]]> + + + false || $var === null) { + $var = true; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml new file mode 100644 index 000000000..a4c9887b2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml new file mode 100644 index 000000000..f4f3e19cb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml new file mode 100644 index 000000000..30e0def93 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml new file mode 100644 index 000000000..2e399b34b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml new file mode 100644 index 000000000..7013ffd90 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml new file mode 100644 index 000000000..bdd36d498 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $var = 1; +} + ]]> + + + $var = 1; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml new file mode 100644 index 000000000..d33b6051d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml @@ -0,0 +1,34 @@ + + + + + + + &...$spread) { + bar(...$spread); + + bar( + [...$foo], + ...array_values($keyedArray) + ); +} + ]]> + + + ... $spread) { + bar(... + $spread + ); + + bar( + [... $foo ],.../*comment*/array_values($keyedArray) + ); +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php new file mode 100644 index 000000000..adb74ec8c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php @@ -0,0 +1,177 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; +use PHP_CodeSniffer\Util\Tokens; + +class ArrayIndentSniff extends AbstractArraySniff +{ + + /** + * The number of spaces each array key should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $tokens = $phpcsFile->getTokens(); + + // Determine how far indented the entire array declaration should be. + $ignore = Tokens::$emptyTokens; + $ignore[] = T_DOUBLE_ARROW; + $ignore[] = T_COMMA; + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $start = $phpcsFile->findStartOfStatement($prev); + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $start, true); + $baseIndent = ($tokens[$first]['column'] - 1); + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $startIndent = ($tokens[$first]['column'] - 1); + + // If the open brace is not indented to at least to the level of the start + // of the statement, the sniff will conflict with other sniffs trying to + // check indent levels because it's not valid. But we don't enforce exactly + // how far indented it should be. + if ($startIndent < $baseIndent) { + $error = 'Array open brace not indented correctly; expected at least %s spaces but found %s'; + $data = [ + $baseIndent, + $startIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OpenBraceIncorrect', $data); + if ($fix === true) { + $padding = str_repeat(' ', $baseIndent); + if ($startIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + } + + return; + }//end if + + $expectedIndent = ($startIndent + $this->indent); + + foreach ($indices as $index) { + if (isset($index['index_start']) === true) { + $start = $index['index_start']; + } else { + $start = $index['value_start']; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$start]['line']) { + // This index isn't the only content on the line + // so we can't check indent rules. + continue; + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $start, true); + + $foundIndent = ($tokens[$first]['column'] - 1); + if ($foundIndent === $expectedIndent) { + continue; + } + + $error = 'Array key not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $first, 'KeyIncorrect', $data); + if ($fix === false) { + continue; + } + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + }//end foreach + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$arrayEnd]['line']) { + $error = 'Closing brace of array declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotNewLine'); + if ($fix === true) { + $padding = $phpcsFile->eolChar.str_repeat(' ', $expectedIndent); + $phpcsFile->fixer->addContentBefore($arrayEnd, $padding); + } + + return; + } + + // The close brace must be indented one stop less. + $expectedIndent -= $this->indent; + $foundIndent = ($tokens[$arrayEnd]['column'] - 1); + if ($foundIndent === $expectedIndent) { + return; + } + + $error = 'Array close brace not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceIncorrect', $data); + if ($fix === false) { + return; + } + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($arrayEnd, $padding); + } else { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), $padding); + } + + }//end processMultiLineArray() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php new file mode 100644 index 000000000..bf7f3ed1c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowLongArraySyntaxSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_ARRAY]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + $error = 'Short array syntax must be used to define arrays'; + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + // Live coding/parse error, just show the error, don't try and fix it. + $phpcsFile->addError($error, $stackPtr, 'Found'); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + + if ($fix === true) { + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $phpcsFile->fixer->beginChangeset(); + + if ($opener === null) { + $phpcsFile->fixer->replaceToken($stackPtr, '[]'); + } else { + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $phpcsFile->fixer->replaceToken($opener, '['); + $phpcsFile->fixer->replaceToken($closer, ']'); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php new file mode 100644 index 000000000..2ba42d673 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowShortArraySyntaxSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_SHORT_ARRAY]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + + $error = 'Short array syntax is not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $opener = $tokens[$stackPtr]['bracket_opener']; + $closer = $tokens[$stackPtr]['bracket_closer']; + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($opener, 'array('); + $phpcsFile->fixer->replaceToken($closer, ')'); + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php new file mode 100644 index 000000000..3243f8b7d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php @@ -0,0 +1,118 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicateClassNameSniff implements Sniff +{ + + /** + * List of classes that have been found during checking. + * + * @var array + */ + protected $foundClasses = []; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $namespace = ''; + $findTokens = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_NAMESPACE, + T_CLOSE_TAG, + ]; + + $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1)); + while ($stackPtr !== false) { + if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) { + // We can stop here. The sniff will continue from the next open + // tag when PHPCS reaches that token, if there is one. + return; + } + + // Keep track of what namespace we are in. + if ($tokens[$stackPtr]['code'] === T_NAMESPACE) { + $nsEnd = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + ], + ($stackPtr + 1), + null, + true + ); + + $namespace = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($nsEnd - $stackPtr - 1))); + $stackPtr = $nsEnd; + } else { + $nameToken = $phpcsFile->findNext(T_STRING, $stackPtr); + $name = $tokens[$nameToken]['content']; + if ($namespace !== '') { + $name = $namespace.'\\'.$name; + } + + $compareName = strtolower($name); + if (isset($this->foundClasses[$compareName]) === true) { + $type = strtolower($tokens[$stackPtr]['content']); + $file = $this->foundClasses[$compareName]['file']; + $line = $this->foundClasses[$compareName]['line']; + $error = 'Duplicate %s name "%s" found; first defined in %s on line %s'; + $data = [ + $type, + $name, + $file, + $line, + ]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } else { + $this->foundClasses[$compareName] = [ + 'file' => $phpcsFile->getFilename(), + 'line' => $tokens[$stackPtr]['line'], + ]; + } + }//end if + + $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1)); + }//end while + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php new file mode 100644 index 000000000..dfd925f91 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php @@ -0,0 +1,124 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OpeningBraceSameLineSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $scopeIdentifier = $phpcsFile->findNext(T_STRING, ($stackPtr + 1)); + $errorData = [strtolower($tokens[$stackPtr]['content']).' '.$tokens[$scopeIdentifier]['content']]; + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData); + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + + // Is the brace on the same line as the class/interface/trait declaration ? + $lastClassLineToken = $phpcsFile->findPrevious(T_WHITESPACE, ($openingBrace - 1), $stackPtr, true); + $lastClassLine = $tokens[$lastClassLineToken]['line']; + $braceLine = $tokens[$openingBrace]['line']; + $lineDifference = ($braceLine - $lastClassLine); + + if ($lineDifference > 0) { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'new line'); + $error = 'Opening brace should be on the same line as the declaration for %s'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnNewLine', $errorData); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($lastClassLineToken, ' {'); + $phpcsFile->fixer->replaceToken($openingBrace, ''); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'same line'); + } + + // Is the opening brace the last thing on the line ? + $next = $phpcsFile->findNext(T_WHITESPACE, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer']) { + // Ignore empty classes. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference > 0) { + return; + } + + // Is there precisely one space before the opening brace ? + if ($tokens[($openingBrace - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($openingBrace - 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($openingBrace - 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space before opening brace; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + if ($length === 0 || $length === '\t') { + $phpcsFile->fixer->addContentBefore($openingBrace, ' '); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php new file mode 100644 index 000000000..8788a912e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php @@ -0,0 +1,171 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class AssignmentInConditionSniff implements Sniff +{ + + /** + * Assignment tokens to trigger on. + * + * Set in the register() method. + * + * @var array + */ + protected $assignmentTokens = []; + + /** + * The tokens that indicate the start of a condition. + * + * @var array + */ + protected $conditionStartTokens = []; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + $this->assignmentTokens = Tokens::$assignmentTokens; + unset($this->assignmentTokens[T_DOUBLE_ARROW]); + + $starters = Tokens::$booleanOperators; + $starters[T_SEMICOLON] = T_SEMICOLON; + $starters[T_OPEN_PARENTHESIS] = T_OPEN_PARENTHESIS; + + $this->conditionStartTokens = $starters; + + return [ + T_IF, + T_ELSEIF, + T_FOR, + T_SWITCH, + T_CASE, + T_WHILE, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Find the condition opener/closer. + if ($token['code'] === T_FOR) { + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($token['parenthesis_opener'] + 1), ($token['parenthesis_closer'])); + if ($semicolon === false) { + return; + } + + $opener = $semicolon; + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($opener + 1), ($token['parenthesis_closer'])); + if ($semicolon === false) { + return; + } + + $closer = $semicolon; + unset($semicolon); + } else if ($token['code'] === T_CASE) { + if (isset($token['scope_opener']) === false) { + return; + } + + $opener = $stackPtr; + $closer = $token['scope_opener']; + } else { + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $opener = $token['parenthesis_opener']; + $closer = $token['parenthesis_closer']; + }//end if + + $startPos = $opener; + + do { + $hasAssignment = $phpcsFile->findNext($this->assignmentTokens, ($startPos + 1), $closer); + if ($hasAssignment === false) { + return; + } + + // Examine whether the left side is a variable. + $hasVariable = false; + $conditionStart = $startPos; + $altConditionStart = $phpcsFile->findPrevious($this->conditionStartTokens, ($hasAssignment - 1), $startPos); + if ($altConditionStart !== false) { + $conditionStart = $altConditionStart; + } + + for ($i = $hasAssignment; $i > $conditionStart; $i--) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ($tokens[$i]['code'] === T_VARIABLE || $tokens[$i]['code'] === T_CLOSE_SQUARE_BRACKET) { + $hasVariable = true; + break; + } + + // If this is a function call or something, we are OK. + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + } + + if ($hasVariable === true) { + $errorCode = 'Found'; + if ($token['code'] === T_WHILE) { + $errorCode = 'FoundInWhileCondition'; + } + + $phpcsFile->addWarning( + 'Variable assignment found within a condition. Did you mean to do a comparison ?', + $hasAssignment, + $errorCode + ); + } + + $startPos = $hasAssignment; + } while ($startPos < $closer); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php new file mode 100644 index 000000000..1c9e40001 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyPHPStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_SEMICOLON, + T_CLOSE_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + // Detect `something();;`. + case 'T_SEMICOLON': + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($prevNonEmpty === false) { + return; + } + + if ($tokens[$prevNonEmpty]['code'] !== T_SEMICOLON + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG_WITH_ECHO + ) { + if (isset($tokens[$prevNonEmpty]['scope_condition']) === false) { + return; + } + + if ($tokens[$prevNonEmpty]['scope_opener'] !== $prevNonEmpty + && $tokens[$prevNonEmpty]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + return; + } + + $scopeOwner = $tokens[$tokens[$prevNonEmpty]['scope_condition']]['code']; + if ($scopeOwner === T_CLOSURE || $scopeOwner === T_ANON_CLASS || $scopeOwner === T_MATCH) { + return; + } + + // Else, it's something like `if (foo) {};` and the semi-colon is not needed. + } + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + $lastCloser = array_pop($nested); + if (isset($tokens[$lastCloser]['parenthesis_owner']) === true + && $tokens[$tokens[$lastCloser]['parenthesis_owner']]['code'] === T_FOR + ) { + // Empty for() condition. + return; + } + } + + $fix = $phpcsFile->addFixableWarning( + 'Empty PHP statement detected: superfluous semi-colon.', + $stackPtr, + 'SemicolonWithoutCodeDetected' + ); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$prevNonEmpty]['code'] === T_OPEN_TAG + || $tokens[$prevNonEmpty]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + // Check for superfluous whitespace after the semi-colon which will be + // removed as the `fixer->replaceToken(($stackPtr + 1), $replacement); + } + } + + for ($i = $stackPtr; $i > $prevNonEmpty; $i--) { + if ($tokens[$i]['code'] !== T_SEMICOLON + && $tokens[$i]['code'] !== T_WHITESPACE + ) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + break; + + // Detect ``. + case 'T_CLOSE_TAG': + $prevNonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($prevNonEmpty === false + || ($tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG_WITH_ECHO) + ) { + return; + } + + $fix = $phpcsFile->addFixableWarning( + 'Empty PHP open/close tag combination detected.', + $prevNonEmpty, + 'EmptyPHPOpenCloseTagsDetected' + ); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = $prevNonEmpty; $i <= $stackPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + break; + + default: + // Deliberately left empty. + break; + }//end switch + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php new file mode 100644 index 000000000..574bb0ba5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php @@ -0,0 +1,97 @@ + + * stmt { + * // foo + * } + * stmt (conditions) { + * // foo + * } + * + * + * @author Manuel Pichler + * @author Greg Sherwood + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyStatementSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_TRY, + T_CATCH, + T_FINALLY, + T_DO, + T_ELSE, + T_ELSEIF, + T_FOR, + T_FOREACH, + T_IF, + T_SWITCH, + T_WHILE, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip statements without a body. + if (isset($token['scope_opener']) === false) { + return; + } + + $next = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($token['scope_opener'] + 1), + ($token['scope_closer'] - 1), + true + ); + + if ($next !== false) { + return; + } + + // Get token identifier. + $name = strtoupper($token['content']); + $error = 'Empty %s statement detected'; + $phpcsFile->addError($error, $stackPtr, 'Detected'.ucfirst(strtolower($name)), [$name]); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php new file mode 100644 index 000000000..f583e9389 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php @@ -0,0 +1,91 @@ + + * class Foo + * { + * public function bar($x) + * { + * for (;true;) true; // No Init or Update part, may as well be: while (true) + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopShouldBeWhileLoopSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip invalid statement. + if (isset($token['parenthesis_opener']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $parts = [ + 0, + 0, + 0, + ]; + $index = 0; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$index; + } else if (isset(Tokens::$emptyTokens[$code]) === false) { + ++$parts[$index]; + } + } + + if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) { + $error = 'This FOR loop can be simplified to a WHILE loop'; + $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php new file mode 100644 index 000000000..62a07b26a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php @@ -0,0 +1,101 @@ + + * class Foo + * { + * public function bar($x) + * { + * $a = array(1, 2, 3, 4); + * for ($i = 0; $i < count($a); $i++) { + * $a[$i] *= $i; + * } + * } + * } + * + * + * @author Greg Sherwood + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopWithTestFunctionCallSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip invalid statement. + if (isset($token['parenthesis_opener']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $position = 0; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$position; + } + + if ($position < 1) { + continue; + } else if ($position > 1) { + break; + } else if ($code !== T_VARIABLE && $code !== T_STRING) { + continue; + } + + // Find next non empty token, if it is a open curly brace we have a + // function call. + $index = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) { + $error = 'Avoid function calls in a FOR loop test part'; + $phpcsFile->addWarning($error, $stackPtr, 'NotAllowed'); + break; + } + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php new file mode 100644 index 000000000..364658db6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php @@ -0,0 +1,134 @@ + + * class Foo + * { + * public function bar($x) + * { + * for ($i = 0; $i < 10; $i++) + * { + * for ($k = 0; $k < 20; $i++) + * { + * echo 'Hello'; + * } + * } + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class JumbledIncrementerSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip for-loop without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Find incrementors for outer loop. + $outer = $this->findIncrementers($tokens, $token); + + // Skip if empty. + if (count($outer) === 0) { + return; + } + + // Find nested for loops. + $start = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $start <= $end; ++$start) { + if ($tokens[$start]['code'] !== T_FOR) { + continue; + } + + $inner = $this->findIncrementers($tokens, $tokens[$start]); + $diff = array_intersect($outer, $inner); + + if (count($diff) !== 0) { + $error = 'Loop incrementor (%s) jumbling with inner loop'; + $data = [join(', ', $diff)]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + } + + }//end process() + + + /** + * Get all used variables in the incrementer part of a for statement. + * + * @param array(integer=>array) $tokens Array with all code sniffer tokens. + * @param array(string=>mixed) $token Current for loop token + * + * @return string[] List of all found incrementer variables. + */ + protected function findIncrementers(array $tokens, array $token) + { + // Skip invalid statement. + if (isset($token['parenthesis_opener']) === false) { + return []; + } + + $start = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $incrementers = []; + $semicolons = 0; + for ($next = $start; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$semicolons; + } else if ($semicolons === 2 && $code === T_VARIABLE) { + $incrementers[] = $tokens[$next]['content']; + } + } + + return $incrementers; + + }//end findIncrementers() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php new file mode 100644 index 000000000..cc9958c58 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php @@ -0,0 +1,93 @@ +true or false + * + * + * class Foo + * { + * public function close() + * { + * if (true) + * { + * // ... + * } + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnconditionalIfStatementSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip if statement without body. + if (isset($token['parenthesis_opener']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $goodCondition = false; + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } else if ($code !== T_TRUE && $code !== T_FALSE) { + $goodCondition = true; + } + } + + if ($goodCondition === false) { + $error = 'Avoid IF statements that are always true or false'; + $phpcsFile->addWarning($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php new file mode 100644 index 000000000..bed67c93c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php @@ -0,0 +1,85 @@ + + * final class Foo + * { + * public final function bar() + * { + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnnecessaryFinalModifierSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip for-statements without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Fetch previous token. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Skip for non final class. + if ($prev === false || $tokens[$prev]['code'] !== T_FINAL) { + return; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $next <= $end; ++$next) { + if ($tokens[$next]['code'] === T_FINAL) { + $error = 'Unnecessary FINAL modifier in FINAL class'; + $phpcsFile->addWarning($error, $next, 'Found'); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php new file mode 100644 index 000000000..58aa29fe8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php @@ -0,0 +1,265 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnusedFunctionParameterSniff implements Sniff +{ + + /** + * The list of class type hints which will be ignored. + * + * @var array + */ + public $ignoreTypeHints = []; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip broken function declarations. + if (isset($token['scope_opener']) === false || isset($token['parenthesis_opener']) === false) { + return; + } + + $errorCode = 'Found'; + $implements = false; + $extends = false; + $classPtr = $phpcsFile->getCondition($stackPtr, T_CLASS); + if ($classPtr !== false) { + $implements = $phpcsFile->findImplementedInterfaceNames($classPtr); + $extends = $phpcsFile->findExtendedClassName($classPtr); + if ($extends !== false) { + $errorCode .= 'InExtendedClass'; + } else if ($implements !== false) { + $errorCode .= 'InImplementedInterface'; + } + } + + $params = []; + $methodParams = $phpcsFile->getMethodParameters($stackPtr); + + // Skip when no parameters found. + $methodParamsCount = count($methodParams); + if ($methodParamsCount === 0) { + return; + } + + foreach ($methodParams as $param) { + if (isset($param['property_visibility']) === true) { + // Ignore constructor property promotion. + continue; + } + + $params[$param['name']] = $stackPtr; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + // Check the end token for arrow functions as + // they can end at a content token due to not having + // a clearly defined closing token. + if ($token['code'] === T_FN) { + ++$end; + } + + $foundContent = false; + $validTokens = [ + T_HEREDOC => T_HEREDOC, + T_NOWDOC => T_NOWDOC, + T_END_HEREDOC => T_END_HEREDOC, + T_END_NOWDOC => T_END_NOWDOC, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + $validTokens += Tokens::$emptyTokens; + + for (; $next <= $end; ++$next) { + $token = $tokens[$next]; + $code = $token['code']; + + // Ignorable tokens. + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } + + if ($foundContent === false) { + // A throw statement as the first content indicates an interface method. + if ($code === T_THROW && $implements !== false) { + return; + } + + // A return statement as the first content indicates an interface method. + if ($code === T_RETURN) { + $tmp = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($tmp === false && $implements !== false) { + return; + } + + // There is a return. + if ($tokens[$tmp]['code'] === T_SEMICOLON && $implements !== false) { + return; + } + + $tmp = $phpcsFile->findNext(Tokens::$emptyTokens, ($tmp + 1), null, true); + if ($tmp !== false && $tokens[$tmp]['code'] === T_SEMICOLON && $implements !== false) { + // There is a return . + return; + } + }//end if + }//end if + + $foundContent = true; + + if ($code === T_VARIABLE && isset($params[$token['content']]) === true) { + unset($params[$token['content']]); + } else if ($code === T_DOLLAR) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_CURLY_BRACKET) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_STRING) { + $varContent = '$'.$tokens[$nextToken]['content']; + if (isset($params[$varContent]) === true) { + unset($params[$varContent]); + } + } + } + } else if ($code === T_DOUBLE_QUOTED_STRING + || $code === T_START_HEREDOC + || $code === T_START_NOWDOC + ) { + // Tokenize strings that can contain variables. + // Make sure the string is re-joined if it occurs over multiple lines. + $content = $token['content']; + for ($i = ($next + 1); $i <= $end; $i++) { + if (isset($validTokens[$tokens[$i]['code']]) === true) { + $content .= $tokens[$i]['content']; + $next++; + } else { + break; + } + } + + $stringTokens = token_get_all(sprintf('', $content)); + foreach ($stringTokens as $stringPtr => $stringToken) { + if (is_array($stringToken) === false) { + continue; + } + + $varContent = ''; + if ($stringToken[0] === T_DOLLAR_OPEN_CURLY_BRACES) { + $varContent = '$'.$stringTokens[($stringPtr + 1)][1]; + } else if ($stringToken[0] === T_VARIABLE) { + $varContent = $stringToken[1]; + } + + if ($varContent !== '' && isset($params[$varContent]) === true) { + unset($params[$varContent]); + } + } + }//end if + }//end for + + if ($foundContent === true && count($params) > 0) { + $error = 'The method parameter %s is never used'; + + // If there is only one parameter and it is unused, no need for additional errorcode toggling logic. + if ($methodParamsCount === 1) { + foreach ($params as $paramName => $position) { + if (in_array($methodParams[0]['type_hint'], $this->ignoreTypeHints, true) === true) { + continue; + } + + $data = [$paramName]; + $phpcsFile->addWarning($error, $position, $errorCode, $data); + } + + return; + } + + $foundLastUsed = false; + $lastIndex = ($methodParamsCount - 1); + $errorInfo = []; + for ($i = $lastIndex; $i >= 0; --$i) { + if ($foundLastUsed !== false) { + if (isset($params[$methodParams[$i]['name']]) === true) { + $errorInfo[$methodParams[$i]['name']] = [ + 'position' => $params[$methodParams[$i]['name']], + 'errorcode' => $errorCode.'BeforeLastUsed', + 'typehint' => $methodParams[$i]['type_hint'], + ]; + } + } else { + if (isset($params[$methodParams[$i]['name']]) === false) { + $foundLastUsed = true; + } else { + $errorInfo[$methodParams[$i]['name']] = [ + 'position' => $params[$methodParams[$i]['name']], + 'errorcode' => $errorCode.'AfterLastUsed', + 'typehint' => $methodParams[$i]['type_hint'], + ]; + } + } + }//end for + + if (count($errorInfo) > 0) { + $errorInfo = array_reverse($errorInfo); + foreach ($errorInfo as $paramName => $info) { + if (in_array($info['typehint'], $this->ignoreTypeHints, true) === true) { + continue; + } + + $data = [$paramName]; + $phpcsFile->addWarning($error, $info['position'], $info['errorcode'], $data); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php new file mode 100644 index 000000000..fded92953 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php @@ -0,0 +1,161 @@ + + * class FooBar { + * public function __construct($a, $b) { + * parent::__construct($a, $b); + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UselessOverridingMethodSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip function without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Get function name. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + + // Get all parameters from method signature. + $signature = []; + foreach ($phpcsFile->getMethodParameters($stackPtr) as $param) { + $signature[] = $param['name']; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } else if ($code === T_RETURN) { + continue; + } + + break; + } + + // Any token except 'parent' indicates correct code. + if ($tokens[$next]['code'] !== T_PARENT) { + return; + } + + // Find next non empty token index, should be double colon. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code. + if ($next === false || $tokens[$next]['code'] !== T_DOUBLE_COLON) { + return; + } + + // Find next non empty token index, should be the function name. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code or other method. + if ($next === false || $tokens[$next]['content'] !== $methodName) { + return; + } + + // Find next non empty token index, should be the open parenthesis. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code. + if ($next === false || $tokens[$next]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $parameters = ['']; + $parenthesisCount = 1; + $count = count($tokens); + for (++$next; $next < $count; ++$next) { + $code = $tokens[$next]['code']; + + if ($code === T_OPEN_PARENTHESIS) { + ++$parenthesisCount; + } else if ($code === T_CLOSE_PARENTHESIS) { + --$parenthesisCount; + } else if ($parenthesisCount === 1 && $code === T_COMMA) { + $parameters[] = ''; + } else if (isset(Tokens::$emptyTokens[$code]) === false) { + $parameters[(count($parameters) - 1)] .= $tokens[$next]['content']; + } + + if ($parenthesisCount === 0) { + break; + } + }//end for + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_SEMICOLON) { + return; + } + + // Check rest of the scope. + for (++$next; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + // Skip for any other content. + if (isset(Tokens::$emptyTokens[$code]) === false) { + return; + } + } + + $parameters = array_map('trim', $parameters); + $parameters = array_filter($parameters); + + if (count($parameters) === count($signature) && $parameters === $signature) { + $phpcsFile->addWarning('Possible useless method overriding detected', $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php new file mode 100644 index 000000000..545319be5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php @@ -0,0 +1,353 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DocCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOC_COMMENT_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['comment_closer']) === false + || ($tokens[$tokens[$stackPtr]['comment_closer']]['content'] === '' + && $tokens[$stackPtr]['comment_closer'] === ($phpcsFile->numTokens - 1)) + ) { + // Don't process an unfinished comment during live coding. + return; + } + + $commentStart = $stackPtr; + $commentEnd = $tokens[$stackPtr]['comment_closer']; + + $empty = [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + + $short = $phpcsFile->findNext($empty, ($stackPtr + 1), $commentEnd, true); + if ($short === false) { + // No content at all. + $error = 'Doc comment is empty'; + $phpcsFile->addError($error, $stackPtr, 'Empty'); + return; + } + + // The first line of the comment should just be the /** code. + if ($tokens[$short]['line'] === $tokens[$stackPtr]['line']) { + $error = 'The open comment tag must be the only content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + $phpcsFile->fixer->addContentBefore($short, '* '); + $phpcsFile->fixer->endChangeset(); + } + } + + // The last line of the comment should just be the */ code. + $prev = $phpcsFile->findPrevious($empty, ($commentEnd - 1), $stackPtr, true); + if ($tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $error = 'The close comment tag must be the only content on the line'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($commentEnd); + } + } + + // Check for additional blank lines at the end of the comment. + if ($tokens[$prev]['line'] < ($tokens[$commentEnd]['line'] - 1)) { + $error = 'Additional blank lines found at end of doc comment'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $commentEnd; $i++) { + if ($tokens[($i + 1)]['line'] === $tokens[$commentEnd]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Check for a comment description. + if ($tokens[$short]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Missing short description in doc comment'; + $phpcsFile->addError($error, $stackPtr, 'MissingShort'); + } else { + // No extra newline before short description. + if ($tokens[$short]['line'] !== ($tokens[$stackPtr]['line'] + 1)) { + $error = 'Doc comment short description must be on the first line'; + $fix = $phpcsFile->addFixableError($error, $short, 'SpacingBeforeShort'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i < $short; $i++) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } else if ($tokens[$i]['line'] === $tokens[$short]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Account for the fact that a short description might cover + // multiple lines. + $shortContent = $tokens[$short]['content']; + $shortEnd = $short; + for ($i = ($short + 1); $i < $commentEnd; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$i]['line'] === ($tokens[$shortEnd]['line'] + 1)) { + $shortContent .= $tokens[$i]['content']; + $shortEnd = $i; + } else { + break; + } + } + } + + if (preg_match('/^\p{Ll}/u', $shortContent) === 1) { + $error = 'Doc comment short description must start with a capital letter'; + $phpcsFile->addError($error, $short, 'ShortNotCapital'); + } + + $long = $phpcsFile->findNext($empty, ($shortEnd + 1), ($commentEnd - 1), true); + if ($long !== false && $tokens[$long]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$long]['line'] !== ($tokens[$shortEnd]['line'] + 2)) { + $error = 'There must be exactly one blank line between descriptions in a doc comment'; + $fix = $phpcsFile->addFixableError($error, $long, 'SpacingBetween'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($shortEnd + 1); $i < $long; $i++) { + if ($tokens[$i]['line'] === $tokens[$shortEnd]['line']) { + continue; + } else if ($tokens[$i]['line'] === ($tokens[$long]['line'] - 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if (preg_match('/^\p{Ll}/u', $tokens[$long]['content']) === 1) { + $error = 'Doc comment long description must start with a capital letter'; + $phpcsFile->addError($error, $long, 'LongNotCapital'); + } + }//end if + }//end if + + if (empty($tokens[$commentStart]['comment_tags']) === true) { + // No tags in the comment. + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + $prev = $phpcsFile->findPrevious($empty, ($firstTag - 1), $stackPtr, true); + if ($tokens[$firstTag]['line'] !== ($tokens[$prev]['line'] + 2) + && $tokens[$prev]['code'] !== T_DOC_COMMENT_OPEN_TAG + ) { + $error = 'There must be exactly one blank line before the tags in a doc comment'; + $fix = $phpcsFile->addFixableError($error, $firstTag, 'SpacingBeforeTags'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $firstTag; $i++) { + if ($tokens[$i]['line'] === $tokens[$firstTag]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $indent = str_repeat(' ', $tokens[$stackPtr]['column']); + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + // Break out the tags into groups and check alignment within each. + // A tag group is one where there are no blank lines between tags. + // The param tag group is special as it requires all @param tags to be inside. + $tagGroups = []; + $groupid = 0; + $paramGroupid = null; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($pos > 0) { + $prev = $phpcsFile->findPrevious( + T_DOC_COMMENT_STRING, + ($tag - 1), + $tokens[$commentStart]['comment_tags'][($pos - 1)] + ); + + if ($prev === false) { + $prev = $tokens[$commentStart]['comment_tags'][($pos - 1)]; + } + + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) { + $groupid++; + } + } + + if ($tokens[$tag]['content'] === '@param') { + if ($paramGroupid !== null + && $paramGroupid !== $groupid + ) { + $error = 'Parameter tags must be grouped together in a doc comment'; + $phpcsFile->addError($error, $tag, 'ParamGroup'); + } + + if ($paramGroupid === null) { + $paramGroupid = $groupid; + } + }//end if + + $tagGroups[$groupid][] = $tag; + }//end foreach + + foreach ($tagGroups as $groupid => $group) { + $maxLength = 0; + $paddings = []; + foreach ($group as $pos => $tag) { + if ($paramGroupid === $groupid + && $tokens[$tag]['content'] !== '@param' + ) { + $error = 'Tag %s cannot be grouped with parameter tags in a doc comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addError($error, $tag, 'NonParamGroup', $data); + } + + $tagLength = $tokens[$tag]['length']; + if ($tagLength > $maxLength) { + $maxLength = $tagLength; + } + + // Check for a value. No value means no padding needed. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string !== false && $tokens[$string]['line'] === $tokens[$tag]['line']) { + $paddings[$tag] = $tokens[($tag + 1)]['length']; + } + } + + // Check that there was single blank line after the tag block + // but account for a multi-line tag comments. + $lastTag = $group[$pos]; + $next = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($lastTag + 3), $commentEnd); + if ($next !== false) { + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_TAG, T_DOC_COMMENT_STRING], ($next - 1), $commentStart); + if ($tokens[$next]['line'] !== ($tokens[$prev]['line'] + 2)) { + $error = 'There must be a single blank line after a tag group'; + $fix = $phpcsFile->addFixableError($error, $lastTag, 'SpacingAfterTagGroup'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $indent = str_repeat(' ', $tokens[$stackPtr]['column']); + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + // Now check paddings. + foreach ($paddings as $tag => $padding) { + $required = ($maxLength - $tokens[$tag]['length'] + 1); + + if ($padding !== $required) { + $error = 'Tag value for %s tag indented incorrectly; expected %s spaces but found %s'; + $data = [ + $tokens[$tag]['content'], + $required, + $padding, + ]; + + $fix = $phpcsFile->addFixableError($error, ($tag + 1), 'TagValueIndent', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($tag + 1), str_repeat(' ', $required)); + } + } + } + }//end foreach + + // If there is a param group, it needs to be first. + if ($paramGroupid !== null && $paramGroupid !== 0) { + $error = 'Parameter tags must be defined first in a doc comment'; + $phpcsFile->addError($error, $tagGroups[$paramGroupid][0], 'ParamNotFirst'); + } + + $foundTags = []; + foreach ($tokens[$stackPtr]['comment_tags'] as $pos => $tag) { + $tagName = $tokens[$tag]['content']; + if (isset($foundTags[$tagName]) === true) { + $lastTag = $tokens[$stackPtr]['comment_tags'][($pos - 1)]; + if ($tokens[$lastTag]['content'] !== $tagName) { + $error = 'Tags must be grouped together in a doc comment'; + $phpcsFile->addError($error, $tag, 'TagsNotGrouped'); + } + + continue; + } + + $foundTags[$tagName] = true; + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php new file mode 100644 index 000000000..84385221e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php @@ -0,0 +1,78 @@ + + * @author Sam Graham + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FixmeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array_diff(Tokens::$commentTokens, Tokens::$phpcsCommentTokens); + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $matches = []; + preg_match('/(?:\A|[^\p{L}]+)fixme([^\p{L}]+(.*)|\Z)/ui', $content, $matches); + if (empty($matches) === false) { + // Clear whitespace and some common characters not required at + // the end of a fixme message to make the error more informative. + $type = 'CommentFound'; + $fixmeMessage = trim($matches[1]); + $fixmeMessage = trim($fixmeMessage, '-:[](). '); + $error = 'Comment refers to a FIXME task'; + $data = [$fixmeMessage]; + if ($fixmeMessage !== '') { + $type = 'TaskFound'; + $error .= ' "%s"'; + } + + $phpcsFile->addError($error, $stackPtr, $type, $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php new file mode 100644 index 000000000..639680461 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class TodoSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array_diff(Tokens::$commentTokens, Tokens::$phpcsCommentTokens); + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $matches = []; + preg_match('/(?:\A|[^\p{L}]+)todo([^\p{L}]+(.*)|\Z)/ui', $content, $matches); + if (empty($matches) === false) { + // Clear whitespace and some common characters not required at + // the end of a to-do message to make the warning more informative. + $type = 'CommentFound'; + $todoMessage = trim($matches[1]); + $todoMessage = trim($todoMessage, '-:[](). '); + $error = 'Comment refers to a TODO task'; + $data = [$todoMessage]; + if ($todoMessage !== '') { + $type = 'TaskFound'; + $error .= ' "%s"'; + } + + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php new file mode 100644 index 000000000..f760fa1c6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php @@ -0,0 +1,188 @@ + + * @author Mark Scherer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowYodaConditionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$comparisonTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $previousIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + $relevantTokens = [ + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_TRUE, + T_FALSE, + T_NULL, + T_LNUMBER, + T_DNUMBER, + T_CONSTANT_ENCAPSED_STRING, + ]; + + if ($previousIndex === false + || in_array($tokens[$previousIndex]['code'], $relevantTokens, true) === false + ) { + return; + } + + if ($tokens[$previousIndex]['code'] === T_CLOSE_SHORT_ARRAY) { + $previousIndex = $tokens[$previousIndex]['bracket_opener']; + if ($this->isArrayStatic($phpcsFile, $previousIndex) === false) { + return; + } + } + + $prevIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), null, true); + if ($prevIndex === false) { + return; + } + + if (in_array($tokens[$prevIndex]['code'], Tokens::$arithmeticTokens, true) === true) { + return; + } + + if ($tokens[$prevIndex]['code'] === T_STRING_CONCAT) { + return; + } + + // Is it a parenthesis. + if ($tokens[$previousIndex]['code'] === T_CLOSE_PARENTHESIS) { + // Check what exists inside the parenthesis. + $closeParenthesisIndex = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokens[$previousIndex]['parenthesis_opener'] - 1), + null, + true + ); + + if ($closeParenthesisIndex === false || $tokens[$closeParenthesisIndex]['code'] !== T_ARRAY) { + if ($tokens[$closeParenthesisIndex]['code'] === T_STRING) { + return; + } + + // If it is not an array check what is inside. + $found = $phpcsFile->findPrevious( + T_VARIABLE, + ($previousIndex - 1), + $tokens[$previousIndex]['parenthesis_opener'] + ); + + // If a variable exists, it is not Yoda. + if ($found !== false) { + return; + } + + // If there is nothing inside the parenthesis, it it not a Yoda. + $opener = $tokens[$previousIndex]['parenthesis_opener']; + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), ($opener + 1), true); + if ($prev === false) { + return; + } + } else if ($tokens[$closeParenthesisIndex]['code'] === T_ARRAY + && $this->isArrayStatic($phpcsFile, $closeParenthesisIndex) === false + ) { + return; + }//end if + }//end if + + $phpcsFile->addError( + 'Usage of Yoda conditions is not allowed; switch the expression order', + $stackPtr, + 'Found' + ); + + }//end process() + + + /** + * Determines if an array is a static definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $arrayToken The position of the array token. + * + * @return bool + */ + public function isArrayStatic(File $phpcsFile, $arrayToken) + { + $tokens = $phpcsFile->getTokens(); + + $arrayEnd = null; + if ($tokens[$arrayToken]['code'] === T_OPEN_SHORT_ARRAY) { + $start = $arrayToken; + $end = $tokens[$arrayToken]['bracket_closer']; + } else if ($tokens[$arrayToken]['code'] === T_ARRAY) { + $start = $tokens[$arrayToken]['parenthesis_opener']; + $end = $tokens[$arrayToken]['parenthesis_closer']; + } else { + return true; + } + + $staticTokens = Tokens::$emptyTokens; + $staticTokens += Tokens::$textStringTokens; + $staticTokens += Tokens::$assignmentTokens; + $staticTokens += Tokens::$equalityTokens; + $staticTokens += Tokens::$comparisonTokens; + $staticTokens += Tokens::$arithmeticTokens; + $staticTokens += Tokens::$operators; + $staticTokens += Tokens::$booleanOperators; + $staticTokens += Tokens::$castTokens; + $staticTokens += Tokens::$bracketTokens; + $staticTokens += [ + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_COMMA => T_COMMA, + T_TRUE => T_TRUE, + T_FALSE => T_FALSE, + ]; + + for ($i = ($start + 1); $i < $end; $i++) { + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + if (isset($staticTokens[$tokens[$i]['code']]) === false) { + return false; + } + } + + return true; + + }//end isArrayStatic() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php new file mode 100644 index 000000000..a67a6a798 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -0,0 +1,381 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InlineControlStructureSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSE, + T_ELSEIF, + T_FOREACH, + T_WHILE, + T_DO, + T_SWITCH, + T_FOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no'); + return; + } + + // Ignore the ELSE in ELSE IF. We'll process the IF part later. + if ($tokens[$stackPtr]['code'] === T_ELSE) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_IF) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_WHILE || $tokens[$stackPtr]['code'] === T_FOR) { + // This could be from a DO WHILE, which doesn't have an opening brace or a while/for without body. + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $afterParensCloser = $phpcsFile->findNext(Tokens::$emptyTokens, ($tokens[$stackPtr]['parenthesis_closer'] + 1), null, true); + if ($afterParensCloser === false) { + // Live coding. + return; + } + + if ($tokens[$afterParensCloser]['code'] === T_SEMICOLON) { + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no'); + return; + } + } + + // In Javascript DO WHILE loops without curly braces are legal. This + // is only valid if a single statement is present between the DO and + // the WHILE. We can detect this by checking only a single semicolon + // is present between them. + if ($tokens[$stackPtr]['code'] === T_WHILE && $phpcsFile->tokenizerType === 'JS') { + $lastDo = $phpcsFile->findPrevious(T_DO, ($stackPtr - 1)); + $lastSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, ($stackPtr - 1)); + if ($lastDo !== false && $lastSemicolon !== false && $lastDo < $lastSemicolon) { + $precedingSemicolon = $phpcsFile->findPrevious(T_SEMICOLON, ($lastSemicolon - 1)); + if ($precedingSemicolon === false || $precedingSemicolon < $lastDo) { + return; + } + } + } + }//end if + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false + && $tokens[$stackPtr]['code'] !== T_ELSE + ) { + if ($tokens[$stackPtr]['code'] !== T_DO) { + // Live coding or parse error. + return; + } + + $nextWhile = $phpcsFile->findNext(T_WHILE, ($stackPtr + 1)); + if ($nextWhile !== false + && isset($tokens[$nextWhile]['parenthesis_opener'], $tokens[$nextWhile]['parenthesis_closer']) === false + ) { + // Live coding or parse error. + return; + } + + unset($nextWhile); + } + + $start = $stackPtr; + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $start = $tokens[$stackPtr]['parenthesis_closer']; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($start + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return; + } + + if ($tokens[$nextNonEmpty]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$nextNonEmpty]['code'] === T_COLON + ) { + // T_CLOSE_CURLY_BRACKET missing, or alternative control structure with + // T_END... missing. Either live coding, parse error or end + // tag in short open tags and scan run with short_open_tag=Off. + // Bow out completely as any further detection will be unreliable + // and create incorrect fixes or cause fixer conflicts. + return ($phpcsFile->numTokens + 1); + } + + unset($nextNonEmpty, $start); + + // This is a control structure without an opening brace, + // so it is an inline statement. + if ($this->error === true) { + $fix = $phpcsFile->addFixableError('Inline control structures are not allowed', $stackPtr, 'NotAllowed'); + } else { + $fix = $phpcsFile->addFixableWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged'); + } + + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'yes'); + + // Stop here if we are not fixing the error. + if ($fix !== true) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $closer = $tokens[$stackPtr]['parenthesis_closer']; + } else { + $closer = $stackPtr; + } + + if ($tokens[($closer + 1)]['code'] === T_WHITESPACE + || $tokens[($closer + 1)]['code'] === T_SEMICOLON + ) { + $phpcsFile->fixer->addContent($closer, ' {'); + } else { + $phpcsFile->fixer->addContent($closer, ' { '); + } + + $fixableScopeOpeners = $this->register(); + + $lastNonEmpty = $closer; + for ($end = ($closer + 1); $end < $phpcsFile->numTokens; $end++) { + if ($tokens[$end]['code'] === T_SEMICOLON) { + break; + } + + if ($tokens[$end]['code'] === T_CLOSE_TAG) { + $end = $lastNonEmpty; + break; + } + + if (in_array($tokens[$end]['code'], $fixableScopeOpeners, true) === true + && isset($tokens[$end]['scope_opener']) === false + ) { + // The best way to fix nested inline scopes is middle-out. + // So skip this one. It will be detected and fixed on a future loop. + $phpcsFile->fixer->rollbackChangeset(); + return; + } + + if (isset($tokens[$end]['scope_opener']) === true) { + $type = $tokens[$end]['code']; + $end = $tokens[$end]['scope_closer']; + if ($type === T_DO + || $type === T_IF || $type === T_ELSEIF + || $type === T_TRY || $type === T_CATCH || $type === T_FINALLY + ) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next === false) { + break; + } + + $nextType = $tokens[$next]['code']; + + // Let additional conditions loop and find their ending. + if (($type === T_IF + || $type === T_ELSEIF) + && ($nextType === T_ELSEIF + || $nextType === T_ELSE) + ) { + continue; + } + + // Account for TRY... CATCH/FINALLY statements. + if (($type === T_TRY + || $type === T_CATCH + || $type === T_FINALLY) + && ($nextType === T_CATCH + || $nextType === T_FINALLY) + ) { + continue; + } + + // Account for DO... WHILE conditions. + if ($type === T_DO && $nextType === T_WHILE) { + $end = $phpcsFile->findNext(T_SEMICOLON, ($next + 1)); + } + } else if ($type === T_CLOSURE) { + // There should be a semicolon after the closing brace. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_SEMICOLON) { + $end = $next; + } + }//end if + + if ($tokens[$end]['code'] !== T_END_HEREDOC + && $tokens[$end]['code'] !== T_END_NOWDOC + ) { + break; + } + }//end if + + if (isset($tokens[$end]['parenthesis_closer']) === true) { + $end = $tokens[$end]['parenthesis_closer']; + $lastNonEmpty = $end; + continue; + } + + if ($tokens[$end]['code'] !== T_WHITESPACE) { + $lastNonEmpty = $end; + } + }//end for + + if ($end === $phpcsFile->numTokens) { + $end = $lastNonEmpty; + } + + $nextContent = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Looks for completely empty statements. + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), ($end + 1), true); + } else { + $next = ($end + 1); + $endLine = $end; + } + + if ($next !== $end) { + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] + ) { + break; + } + } + + if (isset(Tokens::$commentTokens[$tokens[$endLine]['code']]) === false + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || isset(Tokens::$commentTokens[$tokens[($endLine - 1)]['code']]) === false) + ) { + $endLine = $end; + } + } + + if ($endLine !== $end) { + $endToken = $endLine; + $addedContent = ''; + } else { + $endToken = $end; + $addedContent = $phpcsFile->eolChar; + + if ($tokens[$end]['code'] !== T_SEMICOLON + && $tokens[$end]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $phpcsFile->fixer->addContent($end, '; '); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($endToken + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_ELSE + || $tokens[$next]['code'] === T_ELSEIF) + ) { + $phpcsFile->fixer->addContentBefore($next, '} '); + } else { + $indent = ''; + for ($first = $stackPtr; $first > 0; $first--) { + if ($tokens[$first]['column'] === 1) { + break; + } + } + + if ($tokens[$first]['code'] === T_WHITESPACE) { + $indent = $tokens[$first]['content']; + } else if ($tokens[$first]['code'] === T_INLINE_HTML + || $tokens[$first]['code'] === T_OPEN_TAG + ) { + $addedContent = ''; + } + + $addedContent .= $indent.'}'; + if ($next !== false && $tokens[$endToken]['code'] === T_COMMENT) { + $addedContent .= $phpcsFile->eolChar; + } + + $phpcsFile->fixer->addContent($endToken, $addedContent); + }//end if + } else { + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] + ) { + break; + } + } + + if ($tokens[$endLine]['code'] !== T_COMMENT + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || $tokens[($endLine - 1)]['code'] !== T_COMMENT) + ) { + $endLine = $end; + } + } + + if ($endLine !== $end) { + $phpcsFile->fixer->replaceToken($end, ''); + $phpcsFile->fixer->addNewlineBefore($endLine); + $phpcsFile->fixer->addContent($endLine, '}'); + } else { + $phpcsFile->fixer->replaceToken($end, '}'); + } + }//end if + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php new file mode 100644 index 000000000..81284787a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php @@ -0,0 +1,96 @@ + + * @copyright 2013-2014 Roman Levishchenko + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class CSSLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $csslintPath = Config::getExecutablePath('csslint'); + if ($csslintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $cmd = Common::escapeshellcmd($csslintPath).' '.escapeshellarg($fileName).' 2>&1'; + exec($cmd, $output, $retval); + + if (is_array($output) === false) { + return; + } + + $count = count($output); + + for ($i = 0; $i < $count; $i++) { + $matches = []; + $numMatches = preg_match( + '/(error|warning) at line (\d+)/', + $output[$i], + $matches + ); + + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches[2]; + $message = 'csslint says: '.$output[($i + 1)]; + // First line is message with error line and error code. + // Second is error message. + // Third is wrong line in file. + // Fourth is empty line. + $i += 4; + + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + }//end for + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php new file mode 100644 index 000000000..19204718b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ClosureLinterSniff implements Sniff +{ + + /** + * A list of error codes that should show errors. + * + * All other error codes will show warnings. + * + * @var integer + */ + public $errorCodes = []; + + /** + * A list of error codes to ignore. + * + * @var integer + */ + public $ignoreCodes = []; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jslint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $lintPath = Config::getExecutablePath('gjslint'); + if ($lintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $lintPath = Common::escapeshellcmd($lintPath); + $cmd = $lintPath.' --nosummary --notime --unix_mode '.escapeshellarg($fileName); + exec($cmd, $output, $retval); + + if (is_array($output) === false) { + return; + } + + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match('/^(.*):([0-9]+):\(.*?([0-9]+)\)(.*)$/', $finding, $matches); + if ($numMatches === 0) { + continue; + } + + // Skip error codes we are ignoring. + $code = $matches[3]; + if (in_array($code, $this->ignoreCodes) === true) { + continue; + } + + $line = (int) $matches[2]; + $error = trim($matches[4]); + + $message = 'gjslint says: (%s) %s'; + $data = [ + $code, + $error, + ]; + if (in_array($code, $this->errorCodes) === true) { + $phpcsFile->addErrorOnLine($message, $line, 'ExternalToolError', $data); + } else { + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool', $data); + } + }//end foreach + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php new file mode 100644 index 000000000..d11d34705 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php @@ -0,0 +1,113 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ESLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + /** + * ESLint configuration file path. + * + * @var string|null Path to eslintrc. Null to autodetect. + */ + public $configFile = null; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jshint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $eslintPath = Config::getExecutablePath('eslint'); + if ($eslintPath === null) { + return; + } + + $filename = $phpcsFile->getFilename(); + + $configFile = $this->configFile; + if (empty($configFile) === true) { + // Attempt to autodetect. + $candidates = glob('.eslintrc{.js,.yaml,.yml,.json}', GLOB_BRACE); + if (empty($candidates) === false) { + $configFile = $candidates[0]; + } + } + + $eslintOptions = ['--format json']; + if (empty($configFile) === false) { + $eslintOptions[] = '--config '.escapeshellarg($configFile); + } + + $cmd = Common::escapeshellcmd(escapeshellarg($eslintPath).' '.implode(' ', $eslintOptions).' '.escapeshellarg($filename)); + + // Execute! + exec($cmd, $stdout, $code); + + if ($code <= 0) { + // No errors, continue. + return ($phpcsFile->numTokens + 1); + } + + $data = json_decode(implode("\n", $stdout)); + if (json_last_error() !== JSON_ERROR_NONE) { + // Ignore any errors. + return ($phpcsFile->numTokens + 1); + } + + // Data is a list of files, but we only pass a single one. + $messages = $data[0]->messages; + foreach ($messages as $error) { + $message = 'eslint says: '.$error->message; + if (empty($error->fatal) === false || $error->severity === 2) { + $phpcsFile->addErrorOnLine($message, $error->line, 'ExternalTool'); + } else { + $phpcsFile->addWarningOnLine($message, $error->line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php new file mode 100644 index 000000000..06de35940 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php @@ -0,0 +1,95 @@ + + * @author Alexander Wei§ + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JSHintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jshint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $rhinoPath = Config::getExecutablePath('rhino'); + $jshintPath = Config::getExecutablePath('jshint'); + if ($rhinoPath === null && $jshintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + $jshintPath = Common::escapeshellcmd($jshintPath); + + if ($rhinoPath !== null) { + $rhinoPath = Common::escapeshellcmd($rhinoPath); + $cmd = "$rhinoPath \"$jshintPath\" ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + $regex = '`^(?P.+)\(.+:(?P[0-9]+).*:[0-9]+\)$`'; + } else { + $cmd = "$jshintPath ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + $regex = '`^(.+?): line (?P[0-9]+), col [0-9]+, (?P.+)$`'; + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match($regex, $finding, $matches); + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches['line']; + $message = 'jshint says: '.trim($matches['error']); + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php new file mode 100644 index 000000000..cee8ecc5f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php @@ -0,0 +1,80 @@ + + * @author Greg Sherwood + * @copyright 2010-2014 mediaSELF Sp. z o.o. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ByteOrderMarkSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_HTML]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // The BOM will be the very first token in the file. + if ($stackPtr !== 0) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[$stackPtr]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex) { + $errorData = [$bomName]; + $error = 'File contains %s byte order mark, which may corrupt your application'; + $phpcsFile->addError($error, $stackPtr, 'Found', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'yes'); + return; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'no'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php new file mode 100644 index 000000000..d5375dc5c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php @@ -0,0 +1,84 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNewlineSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $stackPtr = ($phpcsFile->numTokens - 1); + + if ($tokens[$stackPtr]['content'] === '') { + $stackPtr--; + } + + $eolCharLen = strlen($phpcsFile->eolChar); + $lastChars = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1)); + if ($lastChars !== $phpcsFile->eolChar) { + $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'no'); + + $error = 'File must end with a newline character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotFound'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($stackPtr); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'yes'); + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php new file mode 100644 index 000000000..41c9c7499 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNoNewlineSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $stackPtr = ($phpcsFile->numTokens - 1); + + if ($tokens[$stackPtr]['content'] === '') { + --$stackPtr; + } + + $eolCharLen = strlen($phpcsFile->eolChar); + $lastChars = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1)); + if ($lastChars === $phpcsFile->eolChar) { + $error = 'File must not end with a newline character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = $stackPtr; $i > 0; $i--) { + $newContent = rtrim($tokens[$i]['content'], $phpcsFile->eolChar); + $phpcsFile->fixer->replaceToken($i, $newContent); + + if ($newContent !== '') { + break; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php new file mode 100644 index 000000000..e1213d5f6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php @@ -0,0 +1,62 @@ + + * @copyright 2019 Matthew Peveler + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ExecutableFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $filename = $phpcsFile->getFilename(); + + if ($filename !== 'STDIN') { + $perms = fileperms($phpcsFile->getFilename()); + if (($perms & 0x0040) !== 0 || ($perms & 0x0008) !== 0 || ($perms & 0x0001) !== 0) { + $error = 'A PHP file should not be executable; found file permissions set to %s'; + $data = [substr(sprintf('%o', $perms), -4)]; + $phpcsFile->addError($error, 0, 'Executable', $data); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php new file mode 100644 index 000000000..eb01da87b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineHTMLSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_HTML]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int|null + */ + public function process(File $phpcsFile, $stackPtr) + { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[0]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex && strlen($tokens[0]['content']) === $bomByteLength) { + return; + } + } + + // Ignore shebang lines. + $tokens = $phpcsFile->getTokens(); + if (substr($tokens[$stackPtr]['content'], 0, 2) === '#!') { + return; + } + + $error = 'PHP files must only contain PHP code'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php new file mode 100644 index 000000000..845e1bcfc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php @@ -0,0 +1,148 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LineEndingsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + /** + * The valid EOL character. + * + * @var string + */ + public $eolChar = '\n'; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $found = $phpcsFile->eolChar; + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\r', $found); + + $phpcsFile->recordMetric($stackPtr, 'EOL char', $found); + + if ($found === $this->eolChar) { + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + } + + // Check for single line files without an EOL. This is a very special + // case and the EOL char is set to \n when this happens. + if ($found === '\n') { + $tokens = $phpcsFile->getTokens(); + $lastToken = ($phpcsFile->numTokens - 1); + if ($tokens[$lastToken]['line'] === 1 + && $tokens[$lastToken]['content'] !== "\n" + ) { + return; + } + } + + $error = 'End of line character is invalid; expected "%s" but found "%s"'; + $expected = $this->eolChar; + $expected = str_replace("\n", '\n', $expected); + $expected = str_replace("\r", '\r', $expected); + $data = [ + $expected, + $found, + ]; + + // Errors are always reported on line 1, no matter where the first PHP tag is. + $fix = $phpcsFile->addFixableError($error, 0, 'InvalidEOLChar', $data); + + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + switch ($this->eolChar) { + case '\n': + $eolChar = "\n"; + break; + case '\r': + $eolChar = "\r"; + break; + case '\r\n': + $eolChar = "\r\n"; + break; + default: + $eolChar = $this->eolChar; + break; + } + + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if (isset($tokens[($i + 1)]) === true + && $tokens[($i + 1)]['line'] <= $tokens[$i]['line'] + ) { + continue; + } + + // Token is the last on a line. + if (isset($tokens[$i]['orig_content']) === true) { + $tokenContent = $tokens[$i]['orig_content']; + } else { + $tokenContent = $tokens[$i]['content']; + } + + if ($tokenContent === '') { + // Special case for JS/CSS close tag. + continue; + } + + $newContent = rtrim($tokenContent, "\r\n"); + $newContent .= $eolChar; + if ($tokenContent !== $newContent) { + $phpcsFile->fixer->replaceToken($i, $newContent); + } + }//end for + }//end if + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php new file mode 100644 index 000000000..5aa45ea0e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php @@ -0,0 +1,201 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LineLengthSniff implements Sniff +{ + + /** + * The limit that the length of a line should not exceed. + * + * @var integer + */ + public $lineLimit = 80; + + /** + * The limit that the length of a line must not exceed. + * + * Set to zero (0) to disable. + * + * @var integer + */ + public $absoluteLineLimit = 100; + + /** + * Whether or not to ignore trailing comments. + * + * This has the effect of also ignoring all lines + * that only contain comments. + * + * @var boolean + */ + public $ignoreComments = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + for ($i = 1; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['column'] === 1) { + $this->checkLineLength($phpcsFile, $tokens, $i); + } + } + + $this->checkLineLength($phpcsFile, $tokens, $i); + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + + /** + * Checks if a line is too long. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tokens The token stack. + * @param int $stackPtr The first token on the next line. + * + * @return void + */ + protected function checkLineLength($phpcsFile, $tokens, $stackPtr) + { + // The passed token is the first on the line. + $stackPtr--; + + if ($tokens[$stackPtr]['column'] === 1 + && $tokens[$stackPtr]['length'] === 0 + ) { + // Blank line. + return; + } + + if ($tokens[$stackPtr]['column'] !== 1 + && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar + ) { + $stackPtr--; + } + + $onlyComment = false; + if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) { + $prevNonWhiteSpace = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['line'] !== $tokens[$prevNonWhiteSpace]['line']) { + $onlyComment = true; + } + } + + if ($onlyComment === true + && isset(Tokens::$phpcsCommentTokens[$tokens[$stackPtr]['code']]) === true + ) { + // Ignore PHPCS annotation comments that are on a line by themselves. + return; + } + + $lineLength = ($tokens[$stackPtr]['column'] + $tokens[$stackPtr]['length'] - 1); + + if ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true + ) { + // Trailing comments are being ignored in line length calculations. + if ($onlyComment === true) { + // The comment is the only thing on the line, so no need to check length. + return; + } + + $lineLength -= $tokens[$stackPtr]['length']; + } + + // Record metrics for common line length groupings. + if ($lineLength <= 80) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '80 or less'); + } else if ($lineLength <= 120) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '81-120'); + } else if ($lineLength <= 150) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '121-150'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Line length', '151 or more'); + } + + if ($onlyComment === true) { + // If this is a long comment, check if it can be broken up onto multiple lines. + // Some comments contain unbreakable strings like URLs and so it makes sense + // to ignore the line length in these cases if the URL would be longer than the max + // line length once you indent it to the correct level. + if ($lineLength > $this->lineLimit) { + $oldLength = strlen($tokens[$stackPtr]['content']); + $newLength = strlen(ltrim($tokens[$stackPtr]['content'], "/#\t ")); + $indent = (($tokens[$stackPtr]['column'] - 1) + ($oldLength - $newLength)); + + $nonBreakingLength = $tokens[$stackPtr]['length']; + + $space = strrpos($tokens[$stackPtr]['content'], ' '); + if ($space !== false) { + $nonBreakingLength -= ($space + 1); + } + + if (($nonBreakingLength + $indent) > $this->lineLimit) { + return; + } + } + }//end if + + if ($this->absoluteLineLimit > 0 + && $lineLength > $this->absoluteLineLimit + ) { + $data = [ + $this->absoluteLineLimit, + $lineLength, + ]; + + $error = 'Line exceeds maximum limit of %s characters; contains %s characters'; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($lineLength > $this->lineLimit) { + $data = [ + $this->lineLimit, + $lineLength, + ]; + + $warning = 'Line exceeds %s characters; contains %s characters'; + $phpcsFile->addWarning($warning, $stackPtr, 'TooLong', $data); + } + + }//end checkLineLength() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php new file mode 100644 index 000000000..a9fd4c5d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php @@ -0,0 +1,70 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercasedFilenameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $filename = $phpcsFile->getFilename(); + if ($filename === 'STDIN') { + return; + } + + $filename = basename($filename); + $lowercaseFilename = strtolower($filename); + if ($filename !== $lowercaseFilename) { + $data = [ + $filename, + $lowercaseFilename, + ]; + $error = 'Filename "%s" doesn\'t match the expected filename "%s"'; + $phpcsFile->addError($error, $stackPtr, 'NotFound', $data); + $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'yes'); + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php new file mode 100644 index 000000000..52d5d84c7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneClassPerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one class is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php new file mode 100644 index 000000000..9a6f5bccd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneInterfacePerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INTERFACE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextInterface = $phpcsFile->findNext($this->register(), $start); + if ($nextInterface !== false) { + $error = 'Only one interface is allowed in a file'; + $phpcsFile->addError($error, $nextInterface, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php new file mode 100644 index 000000000..4d417e069 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneObjectStructurePerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one object structure is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php new file mode 100644 index 000000000..7ae523f70 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Alexander Obuhovich + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneTraitPerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_TRAIT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one trait is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php new file mode 100644 index 000000000..6f9ff9f91 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowMultipleStatementsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SEMICOLON]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $fixable = true; + $prev = $stackPtr; + + do { + $prev = $phpcsFile->findPrevious([T_SEMICOLON, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_PHPCS_IGNORE], ($prev - 1)); + if ($prev === false + || $tokens[$prev]['code'] === T_OPEN_TAG + || $tokens[$prev]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no'); + return; + } + + if ($tokens[$prev]['code'] === T_PHPCS_IGNORE) { + $fixable = false; + } + } while ($tokens[$prev]['code'] === T_PHPCS_IGNORE); + + // Ignore multiple statements in a FOR condition. + foreach ([$stackPtr, $prev] as $checkToken) { + if (isset($tokens[$checkToken]['nested_parenthesis']) === true) { + foreach ($tokens[$checkToken]['nested_parenthesis'] as $bracket) { + if (isset($tokens[$bracket]['parenthesis_owner']) === false) { + // Probably a closure sitting inside a function call. + continue; + } + + $owner = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FOR) { + return; + } + } + } + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'yes'); + + $error = 'Each PHP statement must be on a line by itself'; + $code = 'SameLine'; + if ($fixable === false) { + $phpcsFile->addError($error, $stackPtr, $code); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $code); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($prev); + if ($tokens[($prev + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($prev + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no'); + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php new file mode 100644 index 000000000..802e59448 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php @@ -0,0 +1,426 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultipleStatementAlignmentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = false; + + /** + * The maximum amount of padding before the alignment is ignored. + * + * If the amount of padding required to align this assignment with the + * surrounding assignments exceeds this number, the assignment will be + * ignored and no errors or warnings will be thrown. + * + * @var integer + */ + public $maxPadding = 1000; + + /** + * Controls which side of the assignment token is used for alignment. + * + * @var boolean + */ + public $alignAtEnd = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$assignmentTokens; + unset($tokens[T_DOUBLE_ARROW]); + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $lastAssign = $this->checkAlignment($phpcsFile, $stackPtr); + return ($lastAssign + 1); + + }//end process() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $end The token where checking should end. + * If NULL, the entire file will be checked. + * + * @return int + */ + public function checkAlignment($phpcsFile, $stackPtr, $end=null) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore assignments used in a condition, like an IF or FOR or closure param defaults. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + // If the parenthesis is on the same line as the assignment, + // then it should be ignored as it is specifically being grouped. + $parens = $tokens[$stackPtr]['nested_parenthesis']; + $lastParen = array_pop($parens); + if ($tokens[$lastParen]['line'] === $tokens[$stackPtr]['line']) { + return $stackPtr; + } + + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $start => $end) { + if (isset($tokens[$start]['parenthesis_owner']) === true) { + return $stackPtr; + } + } + } + + $assignments = []; + $prevAssign = null; + $lastLine = $tokens[$stackPtr]['line']; + $maxPadding = null; + $stopped = null; + $lastCode = $stackPtr; + $lastSemi = null; + $arrayEnd = null; + + if ($end === null) { + $end = $phpcsFile->numTokens; + } + + $find = Tokens::$assignmentTokens; + unset($find[T_DOUBLE_ARROW]); + + $scopes = Tokens::$scopeOpeners; + unset($scopes[T_CLOSURE]); + unset($scopes[T_ANON_CLASS]); + unset($scopes[T_OBJECT]); + + for ($assign = $stackPtr; $assign < $end; $assign++) { + if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // Statement is in a different context, so the block is over. + break; + } + + if (isset($tokens[$assign]['scope_opener']) === true + && $tokens[$assign]['level'] === $tokens[$stackPtr]['level'] + ) { + if (isset($scopes[$tokens[$assign]['code']]) === true) { + // This type of scope indicates that the assignment block is over. + break; + } + + // Skip over the scope block because it is seen as part of the assignment block, + // but also process any assignment blocks that are inside as well. + $nextAssign = $phpcsFile->findNext($find, ($assign + 1), ($tokens[$assign]['scope_closer'] - 1)); + if ($nextAssign !== false) { + $assign = $this->checkAlignment($phpcsFile, $nextAssign); + } else { + $assign = $tokens[$assign]['scope_closer']; + } + + $lastCode = $assign; + continue; + } + + if ($assign === $arrayEnd) { + $arrayEnd = null; + } + + if (isset($find[$tokens[$assign]['code']]) === false) { + // A blank line indicates that the assignment block has ended. + if (isset(Tokens::$emptyTokens[$tokens[$assign]['code']]) === false + && ($tokens[$assign]['line'] - $tokens[$lastCode]['line']) > 1 + && $tokens[$assign]['level'] === $tokens[$stackPtr]['level'] + && $arrayEnd === null + ) { + break; + } + + if ($tokens[$assign]['code'] === T_CLOSE_TAG) { + // Breaking out of PHP ends the assignment block. + break; + } + + if ($tokens[$assign]['code'] === T_OPEN_SHORT_ARRAY + && isset($tokens[$assign]['bracket_closer']) === true + ) { + $arrayEnd = $tokens[$assign]['bracket_closer']; + } + + if ($tokens[$assign]['code'] === T_ARRAY + && isset($tokens[$assign]['parenthesis_opener']) === true + && isset($tokens[$tokens[$assign]['parenthesis_opener']]['parenthesis_closer']) === true + ) { + $arrayEnd = $tokens[$tokens[$assign]['parenthesis_opener']]['parenthesis_closer']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$assign]['code']]) === false) { + $lastCode = $assign; + + if ($tokens[$assign]['code'] === T_SEMICOLON) { + if ($tokens[$assign]['conditions'] === $tokens[$stackPtr]['conditions']) { + if ($lastSemi !== null && $prevAssign !== null && $lastSemi > $prevAssign) { + // This statement did not have an assignment operator in it. + break; + } else { + $lastSemi = $assign; + } + } else if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // Statement is in a different context, so the block is over. + break; + } + } + }//end if + + continue; + } else if ($assign !== $stackPtr && $tokens[$assign]['line'] === $lastLine) { + // Skip multiple assignments on the same line. We only need to + // try and align the first assignment. + continue; + }//end if + + if ($assign !== $stackPtr) { + if ($tokens[$assign]['level'] > $tokens[$stackPtr]['level']) { + // Has to be nested inside the same conditions as the first assignment. + // We've gone one level down, so process this new block. + $assign = $this->checkAlignment($phpcsFile, $assign); + $lastCode = $assign; + continue; + } else if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // We've gone one level up, so the block we are processing is done. + break; + } else if ($arrayEnd !== null) { + // Assignments inside arrays are not part of + // the original block, so process this new block. + $assign = ($this->checkAlignment($phpcsFile, $assign, $arrayEnd) - 1); + $arrayEnd = null; + $lastCode = $assign; + continue; + } + + // Make sure it is not assigned inside a condition (eg. IF, FOR). + if (isset($tokens[$assign]['nested_parenthesis']) === true) { + // If the parenthesis is on the same line as the assignment, + // then it should be ignored as it is specifically being grouped. + $parens = $tokens[$assign]['nested_parenthesis']; + $lastParen = array_pop($parens); + if ($tokens[$lastParen]['line'] === $tokens[$assign]['line']) { + break; + } + + foreach ($tokens[$assign]['nested_parenthesis'] as $start => $end) { + if (isset($tokens[$start]['parenthesis_owner']) === true) { + break(2); + } + } + } + }//end if + + $var = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($assign - 1), + null, + true + ); + + // Make sure we wouldn't break our max padding length if we + // aligned with this statement, or they wouldn't break the max + // padding length if they aligned with us. + $varEnd = $tokens[($var + 1)]['column']; + $assignLen = $tokens[$assign]['length']; + if ($this->alignAtEnd !== true) { + $assignLen = 1; + } + + if ($assign !== $stackPtr) { + if ($prevAssign === null) { + // Processing an inner block but no assignments found. + break; + } + + if (($varEnd + 1) > $assignments[$prevAssign]['assign_col']) { + $padding = 1; + $assignColumn = ($varEnd + 1); + } else { + $padding = ($assignments[$prevAssign]['assign_col'] - $varEnd + $assignments[$prevAssign]['assign_len'] - $assignLen); + if ($padding <= 0) { + $padding = 1; + } + + if ($padding > $this->maxPadding) { + $stopped = $assign; + break; + } + + $assignColumn = ($varEnd + $padding); + }//end if + + if (($assignColumn + $assignLen) > ($assignments[$maxPadding]['assign_col'] + $assignments[$maxPadding]['assign_len'])) { + $newPadding = ($varEnd - $assignments[$maxPadding]['var_end'] + $assignLen - $assignments[$maxPadding]['assign_len'] + 1); + if ($newPadding > $this->maxPadding) { + $stopped = $assign; + break; + } else { + // New alignment settings for previous assignments. + foreach ($assignments as $i => $data) { + if ($i === $assign) { + break; + } + + $newPadding = ($varEnd - $data['var_end'] + $assignLen - $data['assign_len'] + 1); + $assignments[$i]['expected'] = $newPadding; + $assignments[$i]['assign_col'] = ($data['var_end'] + $newPadding); + } + + $padding = 1; + $assignColumn = ($varEnd + 1); + } + } else if ($padding > $assignments[$maxPadding]['expected']) { + $maxPadding = $assign; + }//end if + } else { + $padding = 1; + $assignColumn = ($varEnd + 1); + $maxPadding = $assign; + }//end if + + $found = 0; + if ($tokens[($var + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($var + 1)]['length']; + if ($found === 0) { + // This means a newline was found. + $found = 1; + } + } + + $assignments[$assign] = [ + 'var_end' => $varEnd, + 'assign_len' => $assignLen, + 'assign_col' => $assignColumn, + 'expected' => $padding, + 'found' => $found, + ]; + + $lastLine = $tokens[$assign]['line']; + $prevAssign = $assign; + }//end for + + if (empty($assignments) === true) { + return $stackPtr; + } + + $numAssignments = count($assignments); + + $errorGenerated = false; + foreach ($assignments as $assignment => $data) { + if ($data['found'] === $data['expected']) { + continue; + } + + $expectedText = $data['expected'].' space'; + if ($data['expected'] !== 1) { + $expectedText .= 's'; + } + + if ($data['found'] === null) { + $foundText = 'a new line'; + } else { + $foundText = $data['found'].' space'; + if ($data['found'] !== 1) { + $foundText .= 's'; + } + } + + if ($numAssignments === 1) { + $type = 'Incorrect'; + $error = 'Equals sign not aligned correctly; expected %s but found %s'; + } else { + $type = 'NotSame'; + $error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s'; + } + + $errorData = [ + $expectedText, + $foundText, + ]; + + if ($this->error === true) { + $fix = $phpcsFile->addFixableError($error, $assignment, $type, $errorData); + } else { + $fix = $phpcsFile->addFixableWarning($error, $assignment, $type.'Warning', $errorData); + } + + $errorGenerated = true; + + if ($fix === true && $data['found'] !== null) { + $newContent = str_repeat(' ', $data['expected']); + if ($data['found'] === 0) { + $phpcsFile->fixer->addContentBefore($assignment, $newContent); + } else { + $phpcsFile->fixer->replaceToken(($assignment - 1), $newContent); + } + } + }//end foreach + + if ($numAssignments > 1) { + if ($errorGenerated === true) { + $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'yes'); + } + } + + if ($stopped !== null) { + return $this->checkAlignment($phpcsFile, $stopped); + } else { + return $assign; + } + + }//end checkAlignment() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php new file mode 100644 index 000000000..f6a37dafd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.4.0 Use the Generic.Formatting.SpaceAfterCast sniff with + * the $spacing property set to 0 instead. + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NoSpaceAfterCastSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + return; + } + + $error = 'A cast statement must not be followed by a space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFound'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php new file mode 100644 index 000000000..f19489e8e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php @@ -0,0 +1,153 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceAfterCastSniff implements Sniff +{ + + /** + * The number of spaces desired after a cast token. + * + * @var integer + */ + public $spacing = 1; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $this->spacing = (int) $this->spacing; + + if ($tokens[$stackPtr]['code'] === T_BINARY_CAST + && $tokens[$stackPtr]['content'] === 'b' + ) { + // You can't replace a space after this type of binary casting. + return; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($this->ignoreNewlines === true + && $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line'] + ) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 'newline'); + return; + } + + if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0); + return; + } + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== $nextNonWhitespace) { + $error = 'Expected %s space(s) after cast statement; comment found'; + $data = [$this->spacing]; + $phpcsFile->addError($error, $stackPtr, 'CommentFound', $data); + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $tokens[($stackPtr + 1)]['length']); + } else { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0); + } + + return; + } + + $found = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $found = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $found); + + if ($found === $this->spacing) { + return; + } + + $error = 'Expected %s space(s) after cast statement; %s found'; + $data = [ + $this->spacing, + $found, + ]; + + $errorCode = 'TooMuchSpace'; + if ($this->spacing !== 0) { + if ($found === 0) { + $errorCode = 'NoSpace'; + } else if ($found !== 'newline' && $found < $this->spacing) { + $errorCode = 'TooLittleSpace'; + } + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $start = ($stackPtr + 1); + + if ($this->spacing > 0) { + $phpcsFile->fixer->replaceToken($start, $padding); + ++$start; + } + + for ($i = $start; $i < $nextNonWhitespace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php new file mode 100644 index 000000000..b74ca80ed --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php @@ -0,0 +1,135 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceAfterNotSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces desired after the NOT operator. + * + * @var integer + */ + public $spacing = 1; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_BOOLEAN_NOT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $this->spacing = (int) $this->spacing; + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($this->ignoreNewlines === true + && $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line'] + ) { + return; + } + + if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) { + return; + } + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== $nextNonWhitespace) { + $error = 'Expected %s space(s) after NOT operator; comment found'; + $data = [$this->spacing]; + $phpcsFile->addError($error, $stackPtr, 'CommentFound', $data); + return; + } + + $found = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $found = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + } + + if ($found === $this->spacing) { + return; + } + + $error = 'Expected %s space(s) after NOT operator; %s found'; + $data = [ + $this->spacing, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $start = ($stackPtr + 1); + + if ($this->spacing > 0) { + $phpcsFile->fixer->replaceToken($start, $padding); + ++$start; + } + + for ($i = $start; $i < $nextNonWhitespace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php new file mode 100644 index 000000000..a4f85aeb6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceBeforeCastSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['column'] === 1) { + return; + } + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'A cast statement must be preceded by a single space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpace'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before cast statement', 0); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before cast statement', $tokens[($stackPtr - 1)]['length']); + + if ($tokens[($stackPtr - 1)]['column'] !== 1 && $tokens[($stackPtr - 1)]['length'] !== 1) { + $error = 'A cast statement must be preceded by a single space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpace'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php new file mode 100644 index 000000000..425748cee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2009-2014 Florian Grandel + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CallTimePassByReferenceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_VARIABLE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $findTokens = Tokens::$emptyTokens; + $findTokens[] = T_BITWISE_AND; + + $prev = $phpcsFile->findPrevious($findTokens, ($stackPtr - 1), null, true); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $prevCode = $tokens[$prev]['code']; + if ($prevCode === T_FUNCTION || $prevCode === T_CLASS) { + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it cant really be a *call*. + $functionName = $stackPtr; + $openBracket = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($functionName + 1), + null, + true + ); + + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + return; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $nextSeparator = $openBracket; + $find = [ + T_VARIABLE, + T_OPEN_SHORT_ARRAY, + ]; + + while (($nextSeparator = $phpcsFile->findNext($find, ($nextSeparator + 1), $closeBracket)) !== false) { + if (isset($tokens[$nextSeparator]['nested_parenthesis']) === false) { + continue; + } + + if ($tokens[$nextSeparator]['code'] === T_OPEN_SHORT_ARRAY) { + $nextSeparator = $tokens[$nextSeparator]['bracket_closer']; + continue; + } + + // Make sure the variable belongs directly to this function call + // and is not inside a nested function call or array. + $brackets = $tokens[$nextSeparator]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if ($lastBracket !== $closeBracket) { + continue; + } + + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($nextSeparator - 1), + null, + true + ); + + if ($tokens[$tokenBefore]['code'] === T_BITWISE_AND) { + if ($phpcsFile->isReference($tokenBefore) === false) { + continue; + } + + // We also want to ignore references used in assignment + // operations passed as function arguments, but isReference() + // sees them as valid references (which they are). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokenBefore - 1), + null, + true + ); + + if (isset(Tokens::$assignmentTokens[$tokens[$tokenBefore]['code']]) === true) { + continue; + } + + // T_BITWISE_AND represents a pass-by-reference. + $error = 'Call-time pass-by-reference calls are prohibited'; + $phpcsFile->addError($error, $tokenBefore, 'NotAllowed'); + }//end if + }//end while + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php new file mode 100644 index 000000000..ca9223814 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php @@ -0,0 +1,185 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallArgumentSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return[ + T_STRING, + T_ISSET, + T_UNSET, + T_SELF, + T_STATIC, + T_VARIABLE, + T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: + // function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $functionName = $stackPtr; + $ignoreTokens = Tokens::$emptyTokens; + $ignoreTokens[] = T_BITWISE_AND; + $functionKeyword = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true); + if ($tokens[$functionKeyword]['code'] === T_FUNCTION || $tokens[$functionKeyword]['code'] === T_CLASS) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$stackPtr]['scope_condition']) === true + ) { + // Not a function call. + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it can't really be a *call*. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($functionName + 1), null, true); + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + return; + } + + $this->checkSpacing($phpcsFile, $stackPtr, $openBracket); + + }//end process() + + + /** + * Checks the spacing around commas. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * + * @return void + */ + public function checkSpacing(File $phpcsFile, $stackPtr, $openBracket) + { + $tokens = $phpcsFile->getTokens(); + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $nextSeparator = $openBracket; + + $find = [ + T_COMMA, + T_CLOSURE, + T_ANON_CLASS, + T_OPEN_SHORT_ARRAY, + ]; + + while (($nextSeparator = $phpcsFile->findNext($find, ($nextSeparator + 1), $closeBracket)) !== false) { + if ($tokens[$nextSeparator]['code'] === T_CLOSURE + || $tokens[$nextSeparator]['code'] === T_ANON_CLASS + ) { + // Skip closures. + $nextSeparator = $tokens[$nextSeparator]['scope_closer']; + continue; + } else if ($tokens[$nextSeparator]['code'] === T_OPEN_SHORT_ARRAY) { + // Skips arrays using short notation. + $nextSeparator = $tokens[$nextSeparator]['bracket_closer']; + continue; + } + + // Make sure the comma or variable belongs directly to this function call, + // and is not inside a nested function call or array. + $brackets = $tokens[$nextSeparator]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if ($lastBracket !== $closeBracket) { + continue; + } + + if ($tokens[$nextSeparator]['code'] === T_COMMA) { + if ($tokens[($nextSeparator - 1)]['code'] === T_WHITESPACE) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextSeparator - 2), null, true); + if (isset(Tokens::$heredocTokens[$tokens[$prev]['code']]) === false) { + $error = 'Space found before comma in argument list'; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'SpaceBeforeComma'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$prev]['line'] !== $tokens[$nextSeparator]['line']) { + $phpcsFile->fixer->addContent($prev, ','); + $phpcsFile->fixer->replaceToken($nextSeparator, ''); + } else { + $phpcsFile->fixer->replaceToken(($nextSeparator - 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[($nextSeparator + 1)]['code'] !== T_WHITESPACE) { + $error = 'No space found after comma in argument list'; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'NoSpaceAfterComma'); + if ($fix === true) { + $phpcsFile->fixer->addContent($nextSeparator, ' '); + } + } else { + // If there is a newline in the space, then they must be formatting + // each argument on a newline, which is valid, so ignore it. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextSeparator + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$nextSeparator]['line']) { + $space = $tokens[($nextSeparator + 1)]['length']; + if ($space > 1) { + $error = 'Expected 1 space after comma in argument list; %s found'; + $data = [$space]; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'TooMuchSpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextSeparator + 1), ' '); + } + } + } + }//end if + }//end if + }//end while + + }//end checkSpacing() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php new file mode 100644 index 000000000..ff19526a9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php @@ -0,0 +1,227 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningFunctionBraceBsdAllmanSniff implements Sniff +{ + + /** + * Should this sniff check function braces? + * + * @var boolean + */ + public $checkFunctions = true; + + /** + * Should this sniff check closure braces? + * + * @var boolean + */ + public $checkClosures = false; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if (($tokens[$stackPtr]['code'] === T_FUNCTION + && (bool) $this->checkFunctions === false) + || ($tokens[$stackPtr]['code'] === T_CLOSURE + && (bool) $this->checkClosures === false) + ) { + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + } + + // Find the end of the function declaration. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + + $functionLine = $tokens[$prev]['line']; + $braceLine = $tokens[$openingBrace]['line']; + + $lineDifference = ($braceLine - $functionLine); + + $metricType = 'Function'; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $metricType = 'Closure'; + } + + if ($lineDifference === 0) { + $error = 'Opening brace should be on a new line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnSameLine'); + if ($fix === true) { + $hasTrailingAnnotation = false; + for ($nextLine = ($openingBrace + 1); $nextLine < $phpcsFile->numTokens; $nextLine++) { + if ($tokens[$openingBrace]['line'] !== $tokens[$nextLine]['line']) { + break; + } + + if (isset(Tokens::$phpcsCommentTokens[$tokens[$nextLine]['code']]) === true) { + $hasTrailingAnnotation = true; + } + } + + $phpcsFile->fixer->beginChangeset(); + $indent = $phpcsFile->findFirstOnLine([], $openingBrace); + + if ($hasTrailingAnnotation === false || $nextLine === false) { + if ($tokens[$indent]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addContentBefore($openingBrace, $tokens[$indent]['content']); + } + + if ($tokens[($openingBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ''); + } + + $phpcsFile->fixer->addNewlineBefore($openingBrace); + } else { + $phpcsFile->fixer->replaceToken($openingBrace, ''); + $phpcsFile->fixer->addNewlineBefore($nextLine); + $phpcsFile->fixer->addContentBefore($nextLine, '{'); + + if ($tokens[$indent]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addContentBefore($nextLine, $tokens[$indent]['content']); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'same line'); + } else if ($lineDifference > 1) { + $error = 'Opening brace should be on the line after the declaration; found %s blank line(s)'; + $data = [($lineDifference - 1)]; + + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($openingBrace - 1), $closeBracket, true); + if ($prevNonWs !== $prev) { + // There must be a comment between the end of the function declaration and the open brace. + // Report, but don't fix. + $phpcsFile->addError($error, $openingBrace, 'BraceSpacing', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceSpacing', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $openingBrace; $i > $prev; $i--) { + if ($tokens[$i]['line'] === $tokens[$openingBrace]['line']) { + if ($tokens[$i]['column'] === 1) { + $phpcsFile->fixer->addNewLineBefore($i); + } + + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $ignore = Tokens::$phpcsCommentTokens; + $ignore[] = T_WHITESPACE; + $next = $phpcsFile->findNext($ignore, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer']) { + // Ignore empty functions. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference !== 1) { + return; + } + + // We need to actually find the first piece of content on this line, + // as if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + + // The opening brace is on the correct line, now it needs to be + // checked to be correctly indented. + $startColumn = $tokens[$lineStart]['column']; + $braceIndent = $tokens[$openingBrace]['column']; + + if ($braceIndent !== $startColumn) { + $expected = ($startColumn - 1); + $found = ($braceIndent - 1); + + $error = 'Opening brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceIndent', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expected); + if ($found === 0) { + $phpcsFile->fixer->addContentBefore($openingBrace, $indent); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), $indent); + } + } + }//end if + + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'new line'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php new file mode 100644 index 000000000..62eafc120 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php @@ -0,0 +1,184 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningFunctionBraceKernighanRitchieSniff implements Sniff +{ + + /** + * Should this sniff check function braces? + * + * @var boolean + */ + public $checkFunctions = true; + + /** + * Should this sniff check closure braces? + * + * @var boolean + */ + public $checkClosures = false; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return void + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if (($tokens[$stackPtr]['code'] === T_FUNCTION + && (bool) $this->checkFunctions === false) + || ($tokens[$stackPtr]['code'] === T_CLOSURE + && (bool) $this->checkClosures === false) + ) { + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + } + + // Find the end of the function declaration. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + + $functionLine = $tokens[$prev]['line']; + $braceLine = $tokens[$openingBrace]['line']; + + $lineDifference = ($braceLine - $functionLine); + + $metricType = 'Function'; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $metricType = 'Closure'; + } + + if ($lineDifference > 0) { + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'new line'); + $error = 'Opening brace should be on the same line as the declaration'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnNewLine'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prev, ' {'); + $phpcsFile->fixer->replaceToken($openingBrace, ''); + if ($tokens[($openingBrace + 1)]['code'] === T_WHITESPACE + && $tokens[($openingBrace + 2)]['line'] > $tokens[$openingBrace]['line'] + ) { + // Brace is followed by a new line, so remove it to ensure we don't + // leave behind a blank line at the top of the block. + $phpcsFile->fixer->replaceToken(($openingBrace + 1), ''); + + if ($tokens[($openingBrace - 1)]['code'] === T_WHITESPACE + && $tokens[($openingBrace - 1)]['line'] === $tokens[$openingBrace]['line'] + && $tokens[($openingBrace - 2)]['line'] < $tokens[$openingBrace]['line'] + ) { + // Brace is preceded by indent, so remove it to ensure we don't + // leave behind more indent than is required for the first line. + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ''); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'same line'); + }//end if + + $ignore = Tokens::$phpcsCommentTokens; + $ignore[] = T_WHITESPACE; + $next = $phpcsFile->findNext($ignore, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer'] + || $tokens[$next]['code'] === T_CLOSE_TAG + ) { + // Ignore empty functions. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference > 0) { + return; + } + + // We are looking for tabs, even if they have been replaced, because + // we enforce a space here. + if (isset($tokens[($openingBrace - 1)]['orig_content']) === true) { + $spacing = $tokens[($openingBrace - 1)]['orig_content']; + } else { + $spacing = $tokens[($openingBrace - 1)]['content']; + } + + if ($tokens[($openingBrace - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($spacing === "\t") { + $length = '\t'; + } else { + $length = strlen($spacing); + } + + if ($length !== 1) { + $error = 'Expected 1 space before opening brace; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpaceBeforeBrace', $data); + if ($fix === true) { + if ($length === 0 || $length === '\t') { + $phpcsFile->fixer->addContentBefore($openingBrace, ' '); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php new file mode 100644 index 000000000..9bd0dff3d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php @@ -0,0 +1,117 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Mayflower GmbH + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CyclomaticComplexitySniff implements Sniff +{ + + /** + * A complexity higher than this value will throw a warning. + * + * @var integer + */ + public $complexity = 10; + + /** + * A complexity higher than this value will throw an error. + * + * @var integer + */ + public $absoluteComplexity = 20; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore abstract methods. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // Detect start and end of this function definition. + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + + // Predicate nodes for PHP. + $find = [ + T_CASE => true, + T_DEFAULT => true, + T_CATCH => true, + T_IF => true, + T_FOR => true, + T_FOREACH => true, + T_WHILE => true, + T_ELSEIF => true, + T_INLINE_THEN => true, + T_COALESCE => true, + T_COALESCE_EQUAL => true, + T_MATCH_ARROW => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + ]; + + $complexity = 1; + + // Iterate from start to end and count predicate nodes. + for ($i = ($start + 1); $i < $end; $i++) { + if (isset($find[$tokens[$i]['code']]) === true) { + $complexity++; + } + } + + if ($complexity > $this->absoluteComplexity) { + $error = 'Function\'s cyclomatic complexity (%s) exceeds allowed maximum of %s'; + $data = [ + $complexity, + $this->absoluteComplexity, + ]; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($complexity > $this->complexity) { + $warning = 'Function\'s cyclomatic complexity (%s) exceeds %s; consider refactoring the function'; + $data = [ + $complexity, + $this->complexity, + ]; + $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php new file mode 100644 index 000000000..d001dedad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php @@ -0,0 +1,100 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Mayflower GmbH + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NestingLevelSniff implements Sniff +{ + + /** + * A nesting level higher than this value will throw a warning. + * + * @var integer + */ + public $nestingLevel = 5; + + /** + * A nesting level higher than this value will throw an error. + * + * @var integer + */ + public $absoluteNestingLevel = 10; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore abstract methods. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // Detect start and end of this function definition. + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + + $nestingLevel = 0; + + // Find the maximum nesting level of any token in the function. + for ($i = ($start + 1); $i < $end; $i++) { + $level = $tokens[$i]['level']; + if ($nestingLevel < $level) { + $nestingLevel = $level; + } + } + + // We subtract the nesting level of the function itself. + $nestingLevel = ($nestingLevel - $tokens[$stackPtr]['level'] - 1); + + if ($nestingLevel > $this->absoluteNestingLevel) { + $error = 'Function\'s nesting level (%s) exceeds allowed maximum of %s'; + $data = [ + $nestingLevel, + $this->absoluteNestingLevel, + ]; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($nestingLevel > $this->nestingLevel) { + $warning = 'Function\'s nesting level (%s) exceeds %s; consider refactoring the function'; + $data = [ + $nestingLevel, + $this->nestingLevel, + ]; + $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php new file mode 100644 index 000000000..3e3af830d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php @@ -0,0 +1,60 @@ + + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class AbstractClassNamePrefixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($phpcsFile->getClassProperties($stackPtr)['is_abstract'] === false) { + // This class is not abstract so we don't need to check it. + return; + } + + $className = $phpcsFile->getDeclarationName($stackPtr); + if ($className === null) { + // We are not interested in anonymous classes. + return; + } + + $prefix = substr($className, 0, 8); + if (strtolower($prefix) !== 'abstract') { + $phpcsFile->addError('Abstract class names must be prefixed with "Abstract"; found "%s"', $stackPtr, 'Missing', [$className]); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php new file mode 100644 index 000000000..b45112034 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php @@ -0,0 +1,223 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class CamelCapsFunctionNameSniff extends AbstractScopeSniff +{ + + /** + * A list of all PHP magic methods. + * + * @var array + */ + protected $magicMethods = [ + 'construct' => true, + 'destruct' => true, + 'call' => true, + 'callstatic' => true, + 'get' => true, + 'set' => true, + 'isset' => true, + 'unset' => true, + 'sleep' => true, + 'wakeup' => true, + 'serialize' => true, + 'unserialize' => true, + 'tostring' => true, + 'invoke' => true, + 'set_state' => true, + 'clone' => true, + 'debuginfo' => true, + ]; + + /** + * A list of all PHP non-magic methods starting with a double underscore. + * + * These come from PHP modules such as SOAPClient. + * + * @var array + */ + protected $methodsDoubleUnderscore = [ + 'dorequest' => true, + 'getcookies' => true, + 'getfunctions' => true, + 'getlastrequest' => true, + 'getlastrequestheaders' => true, + 'getlastresponse' => true, + 'getlastresponseheaders' => true, + 'gettypes' => true, + 'setcookie' => true, + 'setlocation' => true, + 'setsoapheaders' => true, + 'soapcall' => true, + ]; + + /** + * A list of all PHP magic functions. + * + * @var array + */ + protected $magicFunctions = ['autoload' => true]; + + /** + * If TRUE, the string must not have two capital letters next to each other. + * + * @var boolean + */ + public $strict = true; + + + /** + * Constructs a Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + + $methodNameLc = strtolower($methodName); + $classNameLc = strtolower($className); + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = substr($methodNameLc, 2); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); + } + + // PHP4 constructors are allowed to break our rules. + if ($methodNameLc === $classNameLc) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodNameLc === '_'.$classNameLc) { + return; + } + + // Ignore first underscore in methods prefixed with "_". + $methodName = ltrim($methodName, '_'); + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if (Common::isCamelCaps($methodName, false, true, $this->strict) === false) { + if ($methodProps['scope_specified'] === true) { + $error = '%s method name "%s" is not in camel caps format'; + $data = [ + ucfirst($methodProps['scope']), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); + } else { + $error = 'Method name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + $errorData = [$functionName]; + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === true) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData); + } + + // Ignore first underscore in functions prefixed with "_". + $functionName = ltrim($functionName, '_'); + + if (Common::isCamelCaps($functionName, false, true, $this->strict) === false) { + $error = 'Function name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase function name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php new file mode 100644 index 000000000..a41960637 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php @@ -0,0 +1,163 @@ + + * @author Leif Wickland + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; + +class ConstructorNameSniff extends AbstractScopeSniff +{ + + /** + * The name of the class we are currently checking. + * + * @var string + */ + private $currentClass = ''; + + /** + * A list of functions in the current class. + * + * @var string[] + */ + private $functionList = []; + + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() + { + parent::__construct([T_CLASS, T_ANON_CLASS], [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes this test when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (empty($className) === false) { + // Not an anonymous class. + $className = strtolower($className); + } + + if ($className !== $this->currentClass) { + $this->loadFunctionNamesInScope($phpcsFile, $currScope); + $this->currentClass = $className; + } + + $methodName = strtolower($phpcsFile->getDeclarationName($stackPtr)); + + if ($methodName === $className) { + if (in_array('__construct', $this->functionList, true) === false) { + $error = 'PHP4 style constructors are not allowed; use "__construct()" instead'; + $phpcsFile->addError($error, $stackPtr, 'OldStyle'); + } + } else if ($methodName !== '__construct') { + // Not a constructor. + return; + } + + // Stop if the constructor doesn't have a body, like when it is abstract. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $parentClassName = strtolower($phpcsFile->findExtendedClassName($currScope)); + if ($parentClassName === false) { + return; + } + + $endFunctionIndex = $tokens[$stackPtr]['scope_closer']; + $startIndex = $stackPtr; + while (($doubleColonIndex = $phpcsFile->findNext(T_DOUBLE_COLON, $startIndex, $endFunctionIndex)) !== false) { + if ($tokens[($doubleColonIndex + 1)]['code'] === T_STRING + && strtolower($tokens[($doubleColonIndex + 1)]['content']) === $parentClassName + ) { + $error = 'PHP4 style calls to parent constructors are not allowed; use "parent::__construct()" instead'; + $phpcsFile->addError($error, ($doubleColonIndex + 1), 'OldStyleCall'); + } + + $startIndex = ($doubleColonIndex + 1); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + + /** + * Extracts all the function names found in the given scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function loadFunctionNamesInScope(File $phpcsFile, $currScope) + { + $this->functionList = []; + $tokens = $phpcsFile->getTokens(); + + for ($i = ($tokens[$currScope]['scope_opener'] + 1); $i < $tokens[$currScope]['scope_closer']; $i++) { + if ($tokens[$i]['code'] !== T_FUNCTION) { + continue; + } + + $this->functionList[] = trim(strtolower($phpcsFile->getDeclarationName($i))); + + if (isset($tokens[$i]['scope_closer']) !== false) { + // Skip past nested functions and such. + $i = $tokens[$i]['scope_closer']; + } + } + + }//end loadFunctionNamesInScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php new file mode 100644 index 000000000..c5dc34d48 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php @@ -0,0 +1,54 @@ + + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InterfaceNameSuffixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_INTERFACE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $interfaceName = $phpcsFile->getDeclarationName($stackPtr); + if ($interfaceName === null) { + return; + } + + $suffix = substr($interfaceName, -9); + if (strtolower($suffix) !== 'interface') { + $phpcsFile->addError('Interface names must be suffixed with "Interface"; found "%s"', $stackPtr, 'Missing', [$interfaceName]); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php new file mode 100644 index 000000000..4e3b211df --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php @@ -0,0 +1,54 @@ + + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class TraitNameSuffixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return int[] + */ + public function register() + { + return [T_TRAIT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $traitName = $phpcsFile->getDeclarationName($stackPtr); + if ($traitName === null) { + return; + } + + $suffix = substr($traitName, -5); + if (strtolower($suffix) !== 'trait') { + $phpcsFile->addError('Trait names must be suffixed with "Trait"; found "%s"', $stackPtr, 'Missing', [$traitName]); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php new file mode 100644 index 000000000..db50eb56b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UpperCaseConstantNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_CONST, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_CONST) { + // This is a class constant. + $constant = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($constant === false) { + return; + } + + $constName = $tokens[$constant]['content']; + + if (strtoupper($constName) !== $constName) { + if (strtolower($constName) === $constName) { + $phpcsFile->recordMetric($constant, 'Constant name case', 'lower'); + } else { + $phpcsFile->recordMetric($constant, 'Constant name case', 'mixed'); + } + + $error = 'Class constants must be uppercase; expected %s but found %s'; + $data = [ + strtoupper($constName), + $constName, + ]; + $phpcsFile->addError($error, $constant, 'ClassConstantNotUpperCase', $data); + } else { + $phpcsFile->recordMetric($constant, 'Constant name case', 'upper'); + } + + return; + }//end if + + // Only interested in define statements now. + if (strtolower($tokens[$stackPtr]['content']) !== 'define') { + return; + } + + // Make sure this is not a method call. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_DOUBLE_COLON + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + return; + } + + // If the next non-whitespace token after this token + // is not an opening parenthesis then it is not a function call. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($openBracket === false) { + return; + } + + // The next non-whitespace token must be the constant name. + $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + $constName = $tokens[$constPtr]['content']; + + // Check for constants like self::CONSTANT. + $prefix = ''; + $splitPos = strpos($constName, '::'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 2)); + $constName = substr($constName, ($splitPos + 2)); + } + + // Strip namespace from constant like /foo/bar/CONSTANT. + $splitPos = strrpos($constName, '\\'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 1)); + $constName = substr($constName, ($splitPos + 1)); + } + + if (strtoupper($constName) !== $constName) { + if (strtolower($constName) === $constName) { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'lower'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'mixed'); + } + + $error = 'Constants must be uppercase; expected %s but found %s'; + $data = [ + $prefix.strtoupper($constName), + $prefix.$constName, + ]; + $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); + } else { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'upper'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php new file mode 100644 index 000000000..d455845b5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class BacktickOperatorSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_BACKTICK]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of the backtick operator is forbidden'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php new file mode 100644 index 000000000..f52180dd3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php @@ -0,0 +1,86 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CharacterBeforePHPOpeningTagSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $expected = 0; + if ($stackPtr > 0) { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[0]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex) { + $expected++; + break; + } + } + + // Allow a shebang line. + if (substr($tokens[0]['content'], 0, 2) === '#!') { + $expected++; + } + } + + if ($stackPtr !== $expected) { + $error = 'The opening PHP tag must be the first content in the file'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + // Skip the rest of the file so we don't pick up additional + // open tags, typically embedded in HTML. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php new file mode 100644 index 000000000..d03bf8abe --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php @@ -0,0 +1,54 @@ + + * @copyright 2010-2014 Stefano Kowalke + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingPHPTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closeTag === false) { + $error = 'The PHP open tag does not have a corresponding PHP close tag'; + $phpcsFile->addError($error, $stackPtr, 'NotFound'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php new file mode 100644 index 000000000..42eaa40f4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php @@ -0,0 +1,73 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +class DeprecatedFunctionsSniff extends ForbiddenFunctionsSniff +{ + + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array + */ + public $forbiddenFunctions = []; + + + /** + * Constructor. + * + * Uses the Reflection API to get a list of deprecated functions. + */ + public function __construct() + { + $functions = get_defined_functions(); + + foreach ($functions['internal'] as $functionName) { + $function = new \ReflectionFunction($functionName); + + if ($function->isDeprecated() === true) { + $this->forbiddenFunctions[$functionName] = null; + } + } + + }//end __construct() + + + /** + * Generates the error or warning for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden function + * in the token array. + * @param string $function The name of the forbidden function. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError($phpcsFile, $stackPtr, $function, $pattern=null) + { + $data = [$function]; + $error = 'Function %s() has been deprecated'; + $type = 'Deprecated'; + + if ($this->error === true) { + $phpcsFile->addError($error, $stackPtr, $type, $data); + } else { + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + + }//end addError() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php new file mode 100644 index 000000000..433750adf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowAlternativePHPTagsSniff implements Sniff +{ + + /** + * Whether ASP tags are enabled or not. + * + * @var boolean + */ + private $aspTags = false; + + /** + * The current PHP version. + * + * @var integer + */ + private $phpVersion = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + if ($this->phpVersion === null) { + $this->phpVersion = Config::getConfigData('php_version'); + if ($this->phpVersion === null) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + if ($this->phpVersion < 70000) { + $this->aspTags = (bool) ini_get('asp_tags'); + } + + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + T_INLINE_HTML, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $openTag = $tokens[$stackPtr]; + $content = $openTag['content']; + + if (trim($content) === '') { + return; + } + + if ($openTag['code'] === T_OPEN_TAG) { + if ($content === '<%') { + $error = 'ASP style opening tag used; expected "findClosingTag($phpcsFile, $tokens, $stackPtr, '%>'); + $errorCode = 'ASPOpenTagFound'; + } else if (strpos($content, ''); + $errorCode = 'ScriptOpenTagFound'; + } + + if (isset($error, $closer, $errorCode) === true) { + $data = [$content]; + + if ($closer === false) { + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + $this->addChangeset($phpcsFile, $tokens, $stackPtr, $closer); + } + } + } + + return; + }//end if + + if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO && $content === '<%=') { + $error = 'ASP style opening tag used with echo; expected "findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $snippet = $this->getSnippet($tokens[$nextVar]['content']); + $data = [ + $snippet, + $content, + $snippet, + ]; + + $closer = $this->findClosingTag($phpcsFile, $tokens, $stackPtr, '%>'); + + if ($closer === false) { + $phpcsFile->addError($error, $stackPtr, 'ASPShortOpenTagFound', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ASPShortOpenTagFound', $data); + if ($fix === true) { + $this->addChangeset($phpcsFile, $tokens, $stackPtr, $closer, true); + } + } + + return; + }//end if + + // Account for incorrect script open tags. + if ($openTag['code'] === T_INLINE_HTML + && preg_match('`( + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed new file mode 100644 index 000000000..2a695c896 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed @@ -0,0 +1,14 @@ +
+ +Some content here. + + + + +
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc new file mode 100644 index 000000000..cd5a6620c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc @@ -0,0 +1,6 @@ +
+<% echo $var; %> +

Some text <% echo $var; %> and some more text

+<%= $var . ' and some more text to make sure the snippet works'; %> +

Some text <%= $var %> and some more text

+
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed new file mode 100644 index 000000000..6eafb422e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed @@ -0,0 +1,6 @@ +
+ +

Some text and some more text

+ +

Some text and some more text

+
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc new file mode 100644 index 000000000..ba86345a7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc @@ -0,0 +1,7 @@ + +
+<% echo $var; %> +

Some text <% echo $var; %> and some more text

+<%= $var . ' and some more text to make sure the snippet works'; %> +

Some text <%= $var %> and some more text

+
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php new file mode 100644 index 000000000..953e8ad9b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowAlternativePHPTagsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of all test files to check. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = [$testFileBase.'1.inc']; + + $aspTags = false; + if (PHP_VERSION_ID < 70000) { + $aspTags = (bool) ini_get('asp_tags'); + } + + if ($aspTags === true) { + $testFiles[] = $testFileBase.'2.inc'; + } else { + $testFiles[] = $testFileBase.'3.inc'; + } + + return $testFiles; + + }//end getTestFiles() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowAlternativePHPTagsUnitTest.1.inc': + return [ + 4 => 1, + 7 => 1, + 8 => 1, + 11 => 1, + ]; + case 'DisallowAlternativePHPTagsUnitTest.2.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 5 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'DisallowAlternativePHPTagsUnitTest.3.inc') { + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + ]; + } + + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc new file mode 100644 index 000000000..974e45c05 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc @@ -0,0 +1,16 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php new file mode 100644 index 000000000..7ece55120 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowRequestSuperglobalUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 2 => 1, + 12 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc new file mode 100644 index 000000000..040e62dcb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc @@ -0,0 +1,11 @@ +
+ +Some content here. + + +Some content Some more content + + +
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed new file mode 100644 index 000000000..1ea281a41 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed @@ -0,0 +1,11 @@ +
+ +Some content here. + + +Some content Some more content + + +
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc new file mode 100644 index 000000000..85617ded6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc @@ -0,0 +1,8 @@ +
+ +Some content Some more content + + +
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed new file mode 100644 index 000000000..afe5d8f2b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed @@ -0,0 +1,8 @@ +
+ +Some content Some more content + + +
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc new file mode 100644 index 000000000..9b7ccd6dc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc @@ -0,0 +1,16 @@ +// Test warning for when short_open_tag is off. + +Some content Some more content + +// Test multi-line. +Some content Some more content + +// Make sure skipping works. +Some content Some more content + +// Only recognize closing tag after opener. +Some?> content + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowShortOpenTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of all test files to check. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = [$testFileBase.'1.inc']; + + $option = (bool) ini_get('short_open_tag'); + if ($option === true) { + $testFiles[] = $testFileBase.'2.inc'; + } else { + $testFiles[] = $testFileBase.'3.inc'; + } + + return $testFiles; + + }//end getTestFiles() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowShortOpenTagUnitTest.1.inc': + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 10 => 1, + ]; + case 'DisallowShortOpenTagUnitTest.2.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 7 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'DisallowShortOpenTagUnitTest.1.inc': + return []; + case 'DisallowShortOpenTagUnitTest.3.inc': + return [ + 3 => 1, + 6 => 1, + 11 => 1, + ]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc new file mode 100644 index 000000000..f564215b0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc @@ -0,0 +1,18 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DiscourageGotoUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 3 => 1, + 6 => 1, + 11 => 1, + 16 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc new file mode 100644 index 000000000..b30f0dde9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc @@ -0,0 +1,57 @@ +sizeof($array); +$size = $class->count($array); +$class->delete($filepath); +$class->unset($filepath); + +function delete() {} +function unset() {} +function sizeof() {} +function count() {} + +trait DelProvider { + public function delete() { + //irrelevant + } +} + +class LeftSideTest { + use DelProvider { + delete as protected unsetter; + } +} + +class RightSideTest { + use DelProvider { + delete as delete; + } +} + +class RightSideVisTest { + use DelProvider { + delete as protected delete; + DelProvider::delete insteadof delete; + } +} + +namespace Something\sizeof; +$var = new Sizeof(); +class SizeOf implements Something {} + +function mymodule_form_callback(SizeOf $sizeof) { +} + +$size = $class?->sizeof($array); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php new file mode 100644 index 000000000..760e80786 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForbiddenFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 2 => 1, + 4 => 1, + 6 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc new file mode 100644 index 000000000..0307a0559 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc @@ -0,0 +1,100 @@ +NULL = 7; + +use Zend\Log\Writer\NULL as NullWriter; +new \Zend\Log\Writer\NULL(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?FALSE:true; +$x = $f? FALSE:true; + +class MyClass +{ + // Spice things up a little. + const TRUE = false; +} + +var_dump(MyClass::TRUE); + +function tRUE() {} + +$input->getFilterChain()->attachByName('Null', ['type' => Null::TYPE_STRING]); + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = FALSE; + + public int|FALSE $int = FALSE; + public Type|NULL $int = new MyObj(NULL); + + private function typed(int|FALSE $param = NULL, Type|NULL $obj = new MyObj(FALSE)) : string|FALSE|NULL + { + if (TRUE === FALSE) { + return NULL; + } + } +} + +$cl = function (int|FALSE $param = NULL, Type|NULL $obj = new MyObj(FALSE)) : string|FALSE|NULL {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed new file mode 100644 index 000000000..3a6b094c8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc.fixed @@ -0,0 +1,100 @@ +NULL = 7; + +use Zend\Log\Writer\NULL as NullWriter; +new \Zend\Log\Writer\NULL(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?false:true; +$x = $f? false:true; + +class MyClass +{ + // Spice things up a little. + const TRUE = false; +} + +var_dump(MyClass::TRUE); + +function tRUE() {} + +$input->getFilterChain()->attachByName('Null', ['type' => Null::TYPE_STRING]); + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = false; + + public int|FALSE $int = false; + public Type|NULL $int = new MyObj(null); + + private function typed(int|FALSE $param = null, Type|NULL $obj = new MyObj(false)) : string|FALSE|NULL + { + if (true === false) { + return null; + } + } +} + +$cl = function (int|FALSE $param = null, Type|NULL $obj = new MyObj(false)) : string|FALSE|NULL {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js new file mode 100644 index 000000000..87cfb820c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js @@ -0,0 +1,14 @@ +if (variable === true) { } +if (variable === TRUE) { } +if (variable === True) { } +variable = True; + +if (variable === false) { } +if (variable === FALSE) { } +if (variable === False) { } +variable = false; + +if (variable === null) { } +if (variable === NULL) { } +if (variable === Null) { } +variable = NULL; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed new file mode 100644 index 000000000..7dbf3adf5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed @@ -0,0 +1,14 @@ +if (variable === true) { } +if (variable === true) { } +if (variable === true) { } +variable = true; + +if (variable === false) { } +if (variable === false) { } +if (variable === false) { } +variable = false; + +if (variable === null) { } +if (variable === null) { } +if (variable === null) { } +variable = null; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php new file mode 100644 index 000000000..2fb2d6f6d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowerCaseConstantUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='LowerCaseConstantUnitTest.inc') + { + switch ($testFile) { + case 'LowerCaseConstantUnitTest.inc': + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 23 => 1, + 26 => 1, + 31 => 1, + 32 => 1, + 39 => 1, + 42 => 1, + 47 => 1, + 48 => 1, + 70 => 1, + 71 => 1, + 87 => 1, + 89 => 1, + 90 => 1, + 92 => 2, + 94 => 2, + 95 => 1, + 100 => 2, + ]; + break; + case 'LowerCaseConstantUnitTest.js': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 7 => 1, + 8 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc new file mode 100644 index 000000000..37579d321 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc @@ -0,0 +1,48 @@ + $x; +$r = Match ($x) { + 1 => 1, + 2 => 2, + DEFAULT, => 3, +}; + +class Reading { + Public READOnly int $var; +} + +EnuM ENUM: string +{ + Case HEARTS; +} + +__HALT_COMPILER(); // An exception due to phar support. +function diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed new file mode 100644 index 000000000..7063327ae --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed @@ -0,0 +1,48 @@ + $x; +$r = match ($x) { + 1 => 1, + 2 => 2, + default, => 3, +}; + +class Reading { + public readonly int $var; +} + +enum ENUM: string +{ + case HEARTS; +} + +__HALT_COMPILER(); // An exception due to phar support. +function diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php new file mode 100644 index 000000000..6d08e1275 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowerCaseKeywordUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 3, + 11 => 4, + 12 => 1, + 13 => 3, + 14 => 7, + 15 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 25 => 1, + 28 => 1, + 31 => 1, + 32 => 1, + 35 => 1, + 39 => 2, + 42 => 1, + 44 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc new file mode 100644 index 000000000..ac2a1f9e9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowerCaseTypeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 21 => 4, + 22 => 3, + 23 => 3, + 25 => 1, + 26 => 2, + 27 => 2, + 32 => 4, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 43 => 2, + 44 => 1, + 46 => 1, + 49 => 1, + 51 => 2, + 53 => 1, + 55 => 2, + 60 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 71 => 3, + 72 => 2, + 73 => 3, + 74 => 3, + 78 => 3, + 82 => 2, + 85 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc new file mode 100644 index 000000000..72bffe2c4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc @@ -0,0 +1,10 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NoSilencedErrorsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 5 => 1, + 10 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc new file mode 100644 index 000000000..387cec240 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc @@ -0,0 +1,8 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class RequireStrictTypesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'RequireStrictTypesUnitTest.1.inc': + return []; + break; + } + + return [1 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc new file mode 100644 index 000000000..f0f350f37 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc @@ -0,0 +1,5 @@ +php_sapi_name() === true) {} +if ($object?->php_sapi_name() === true) {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php new file mode 100644 index 000000000..08c0ccdcf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SAPIUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [2 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc new file mode 100644 index 000000000..4f0d9d84e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc @@ -0,0 +1,4 @@ + +
text
+ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php new file mode 100644 index 000000000..98d205ce4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php @@ -0,0 +1,59 @@ + + * @author Blaine Schmeisser + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SyntaxUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SyntaxUnitTest.1.inc': + case 'SyntaxUnitTest.2.inc': + return [3 => 1]; + break; + default: + return []; + break; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc new file mode 100644 index 000000000..30c6d2980 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc @@ -0,0 +1,98 @@ +null = 7; + +use Zend\Log\Writer\Null as NullWriter; +new \Zend\Log\Writer\Null(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?false:TRUE; +$x = $f? false:TRUE; + +class MyClass +{ + // Spice things up a little. + const true = FALSE; +} + +var_dump(MyClass::true); + +function true() {} + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = false; + + public int|false $int = false; + public Type|null $int = new MyObj(null); + + private function typed(int|false $param = null, Type|null $obj = new MyObj(false)) : string|false|null + { + if (true === false) { + return null; + } + } +} + +$cl = function (int|false $param = null, Type|null $obj = new MyObj(false)) : string|false|null {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed new file mode 100644 index 000000000..7705198c8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed @@ -0,0 +1,98 @@ +null = 7; + +use Zend\Log\Writer\Null as NullWriter; +new \Zend\Log\Writer\Null(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?FALSE:TRUE; +$x = $f? FALSE:TRUE; + +class MyClass +{ + // Spice things up a little. + const true = FALSE; +} + +var_dump(MyClass::true); + +function true() {} + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = FALSE; + + public int|false $int = FALSE; + public Type|null $int = new MyObj(NULL); + + private function typed(int|false $param = NULL, Type|null $obj = new MyObj(FALSE)) : string|false|null + { + if (TRUE === FALSE) { + return NULL; + } + } +} + +$cl = function (int|false $param = NULL, Type|null $obj = new MyObj(FALSE)) : string|false|null {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php new file mode 100644 index 000000000..30e577633 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UpperCaseConstantUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 23 => 1, + 26 => 1, + 31 => 1, + 32 => 1, + 39 => 1, + 42 => 1, + 47 => 1, + 48 => 1, + 70 => 1, + 71 => 1, + 85 => 1, + 87 => 1, + 88 => 1, + 90 => 2, + 92 => 2, + 93 => 1, + 98 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc new file mode 100644 index 000000000..43c05a111 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.inc @@ -0,0 +1,21 @@ +'; +$code = '<'.'?php '; + +$string = 'This is a really long string. ' + . 'It is being used for errors. ' + . 'The message is not translated.'; +?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js new file mode 100644 index 000000000..6be790086 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js @@ -0,0 +1,15 @@ +var x = 'My ' + 'string'; +var x = 'My ' + 1234; +var x = 'My ' + y + ' test'; + +this.errors['test'] = x; +this.errors['test' + 10] = x; +this.errors['test' + y] = x; +this.errors['test' + 'blah'] = x; +this.errors[y] = x; +this.errors[y + z] = x; +this.errors[y + z + 'My' + 'String'] = x; + +var long = 'This is a really long string. ' + + 'It is being used for errors. ' + + 'The message is not translated.'; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php new file mode 100644 index 000000000..6a9284822 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UnnecessaryStringConcatUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='UnnecessaryStringConcatUnitTest.inc') + { + switch ($testFile) { + case 'UnnecessaryStringConcatUnitTest.inc': + return [ + 2 => 1, + 6 => 1, + 9 => 1, + 12 => 1, + 19 => 1, + 20 => 1, + ]; + break; + case 'UnnecessaryStringConcatUnitTest.js': + return [ + 1 => 1, + 8 => 1, + 11 => 1, + 14 => 1, + 15 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css new file mode 100644 index 000000000..de84a948e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css @@ -0,0 +1,35 @@ +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ + +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; +<<<<<<< HEAD + line-height: -25px; +======= + line-height: -20px; +>>>>>>> ref/heads/feature-branch + cursor: pointer; + -moz-user-select: none; +} + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries, subsequent boundaries will still + * be detected correctly. + */ + +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc new file mode 100644 index 000000000..470c3b8f1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc @@ -0,0 +1,61 @@ +> -1); +var_dump( +1 +<< +-1 +); + +$string = +<< 'a' +<<<<<<< HEAD + 'b' => 'b' +======= + 'c' => 'c' +>>>>>>> master + ); + } + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +/* + * Testing detecting subsequent merge conflicts. + * +<<<<<<< HEAD + * @var string $bar + */ +public function foo($bar){ } + +/** +============ +The above is not the boundary, the below is. +======= + * @var string $bar +>>>>>>> f19f8a5... Commit message +*/ + +// Test that stray boundaries, i.e. an opener without closer and such, are detected. +<<<<<<< HEAD +$a = 1; +======= diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css new file mode 100644 index 000000000..6caa78d02 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css @@ -0,0 +1,32 @@ +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict started in a comment, ending in a CSS block. + */ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; +======= + * which should be detected. + **/ +.SettingsTabPaneWidgetType-tab-start { + line-height: -25px; +>>>>>>> ref/heads/feature-branch + cursor: pointer; + -moz-user-select: none; +} + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries, subsequent boundaries will still + * be detected correctly. + */ + +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc new file mode 100644 index 000000000..809b17d6a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc @@ -0,0 +1,31 @@ +>>>>>> master + */ + +/* + * Testing detecting merge conflicts using different comment styles. + * +<<<<<<< HEAD + * @var string $bar + */ +public function foo($bar){ } + +/* +======= + * @var string $bar +>>>>>>> master +*/ + +// Comment +<<<<<<< HEAD +// Second comment line. NOTE: The above opener breaks the tokenizer. +======= +// New second comment line +>>>>>>> master +// Third comment line diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc new file mode 100644 index 000000000..ce709412b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc @@ -0,0 +1,43 @@ + +
+<<<<<<< HEAD +

Testing a merge conflict.

+======= +

Another text string.

+>>>>>>> ref/heads/feature-branch +
+ + +
+<<<<<<< HEAD +

+======= +

+>>>>>>> ref/heads/feature-branch +
+ +>>>>>> master + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ +?> + +
+<<<<<<< HEAD +

Testing a merge conflict.

+======= +

Another text string.

+>>>>>>> ref/heads/feature-branch +
diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc new file mode 100644 index 000000000..99c0b9971 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc @@ -0,0 +1,71 @@ +>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +// Heredoc with a merge conflict starter, the closer is outside the heredoc. +$string = +<<>>>>>> ref/heads/other-branchname + +// Merge conflict starter outside with a closer inside of the heredoc. +// This breaks the tokenizer. +<<<<<<< HEAD +$string = +<<>>>>>> ref/heads/other-branchname +EOD; + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = +<<>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +$string = +<<>>>>>> ref/heads/other-branchname diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc new file mode 100644 index 000000000..7d55f6df4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc @@ -0,0 +1,34 @@ +>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +// Break the tokenizer. +<<<<<<< HEAD + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = +<<<'EOD' +can be problematic. +<<<<<<< HEAD +were previously not detected. +======= +should also be detected. +>>>>>>> ref/heads/other-branchname +And now they are. +EOD; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc new file mode 100644 index 000000000..aaea32450 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc @@ -0,0 +1,34 @@ +>>>>>> ref/heads/other-branchname + And now they are. + EOD; + +// Break the tokenizer. +>>>>>>> master + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = + <<<"EOD" + Merge conflicts in PHP 7.3 indented heredocs +<<<<<<< HEAD + can be problematic. +======= + should also be detected. +>>>>>>> ref/heads/other-branchname + And now they are. + EOD; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc new file mode 100644 index 000000000..85cae1fdc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc @@ -0,0 +1,19 @@ + +
+<<<<<<< HEAD +

Testing a merge conflict.

+======= +

Another text string.

+>>>>>>> ref/heads/feature-branch +
+ + +
+<<<<<<< HEAD +

+======= +

+>>>>>>> ref/heads/feature-branch +
+ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js new file mode 100644 index 000000000..cd7bc760f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js @@ -0,0 +1,33 @@ + +result = x?y:z; +result = x ? y : z; + +<<<<<<< HEAD +if (something === true +======= +if (something === false +>>>>>>> develop + ^ somethingElse === true +) { +<<<<<<< HEAD + return true; +======= + return false; +>>>>>>> develop +} + +y = 1 + + 2 + - 3; + +/* +<<<<<<< HEAD + * @var string $bar + */ +if (something === true + +/** +======= + * @var string $foo +>>>>>>> master + */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php new file mode 100644 index 000000000..50986f48b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php @@ -0,0 +1,170 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\VersionControl; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GitMergeConflictUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='GitMergeConflictUnitTest.1.inc') + { + switch ($testFile) { + case 'GitMergeConflictUnitTest.1.inc': + return [ + 26 => 1, + 28 => 1, + 30 => 1, + 45 => 1, + 53 => 1, + 55 => 1, + 59 => 1, + 61 => 1, + ]; + + case 'GitMergeConflictUnitTest.2.inc': + return [ + 4 => 1, + 6 => 1, + 8 => 1, + 14 => 1, + 20 => 1, + 22 => 1, + 26 => 1, + 28 => 1, + 30 => 1, + ]; + + case 'GitMergeConflictUnitTest.3.inc': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 22 => 1, + 24 => 1, + 26 => 1, + 38 => 1, + 40 => 1, + 42 => 1, + ]; + + case 'GitMergeConflictUnitTest.4.inc': + return [ + 6 => 1, + 8 => 1, + 10 => 1, + 18 => 1, + 22 => 1, + 25 => 1, + 29 => 1, + 34 => 1, + 39 => 1, + 53 => 1, + 55 => 1, + 57 => 1, + 64 => 1, + 68 => 1, + 71 => 1, + ]; + case 'GitMergeConflictUnitTest.5.inc': + case 'GitMergeConflictUnitTest.6.inc': + return [ + 6 => 1, + 8 => 1, + 10 => 1, + 15 => 1, + 28 => 1, + 30 => 1, + 32 => 1, + ]; + + case 'GitMergeConflictUnitTest.7.inc': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + ]; + + case 'GitMergeConflictUnitTest.1.css': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 30 => 1, + 32 => 1, + 34 => 1, + ]; + + case 'GitMergeConflictUnitTest.2.css': + return [ + 3 => 1, + 8 => 1, + 13 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + ]; + + case 'GitMergeConflictUnitTest.js': + return [ + 5 => 1, + 7 => 1, + 9 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 24 => 1, + 30 => 1, + 32 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc new file mode 100644 index 000000000..e4110dee1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc @@ -0,0 +1,3 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\VersionControl; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SubversionPropertiesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + // This sniff cannot be tested as no SVN version control directory is available. + return true; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc new file mode 100644 index 000000000..bad3998f9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc @@ -0,0 +1,165 @@ +{$var}( $foo,$bar ); + +$bar(function( $a, $b ) { + return function( $c, $d ) use ( $a, $b ) { + echo $a, $b, $c, $d; + }; +})( 'a','b' )( 'c','d' ); + +$closure( $foo,$bar ); +$var = $closure() + $closure( $foo,$bar ) + self::$closure( $foo,$bar ); + +class Test { + public static function baz( $foo, $bar ) { + $a = new self( $foo,$bar ); + $b = new static( $foo,$bar ); + } +} + +/* + * Test warning for empty parentheses. + */ +$a = 4 + (); // Warning. +$a = 4 + ( ); // Warning. +$a = 4 + (/* Not empty */); + +/* + * Test the actual sniff. + */ +if ((null !== $extra) && ($row->extra !== $extra)) {} + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} // Bad x 4. + +if (( null !== $extra // Bad x 1. + && is_int($extra)) + && ( $row->extra !== $extra // Bad x 1. + || $something ) // Bad x 1. +) {} + +if (( null !== $extra ) // Bad x 2. + && ( $row->extra !== $extra ) // Bad x 2. +) {} + +$a = (null !== $extra); +$a = ( null !== $extra ); // Bad x 2. + +$sx = $vert ? ($w - 1) : 0; + +$this->is_overloaded = ( ( ini_get("mbstring.func_overload") & 2 ) != 0 ) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} + +$directory = ('/' == $file[ strlen($file)-1 ]); + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ((null !== $extra) && ($row->extra !== $extra)) {} // Bad x 4. + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} + +if (( null !== $extra // Bad x 1. + && is_int($extra)) // Bad x 1. + && ( $row->extra !== $extra + || $something ) // Bad x 1. +) {} + +if ((null !== $extra) // Bad x 2. + && ($row->extra !== $extra) // Bad x 2. +) {} + +$a = (null !== $extra); // Bad x 2. +$a = ( null !== $extra ); + +$sx = $vert ? ($w - 1) : 0; // Bad x 2. + +$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); // Bad x 4. + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} // Bad x 2. + +$directory = ('/' == $file[ strlen($file)-1 ]); // Bad x 2. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +/* + * Test handling of ignoreNewlines. + */ +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} // Bad x 4, 1 x line 123, 2 x line 125, 1 x line 127. + + +$a = ( + null !== $extra +); // Bad x 2, 1 x line 131, 1 x line 133. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} // Bad x 4, 1 x line 137, 2 x line 139, 1 x line 141. + +$a = ( + null !== $extra +); // Bad x 2, 1 x line 144, 1 x line 146. +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines true +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} + +$a = ( + null !== $extra +); +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines false + +if (true) {} ( 1+2) === 3 ? $a = 1 : $a = 2; +class A {} ( 1+2) === 3 ? $a = 1 : $a = 2; +function foo() {} ( 1+2) === 3 ? $a = 1 : $a = 2; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..08fcd6244 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.inc.fixed @@ -0,0 +1,153 @@ +{$var}( $foo,$bar ); + +$bar(function( $a, $b ) { + return function( $c, $d ) use ( $a, $b ) { + echo $a, $b, $c, $d; + }; +})( 'a','b' )( 'c','d' ); + +$closure( $foo,$bar ); +$var = $closure() + $closure( $foo,$bar ) + self::$closure( $foo,$bar ); + +class Test { + public static function baz( $foo, $bar ) { + $a = new self( $foo,$bar ); + $b = new static( $foo,$bar ); + } +} + +/* + * Test warning for empty parentheses. + */ +$a = 4 + (); // Warning. +$a = 4 + ( ); // Warning. +$a = 4 + (/* Not empty */); + +/* + * Test the actual sniff. + */ +if ((null !== $extra) && ($row->extra !== $extra)) {} + +if ((null !== $extra) && ($row->extra !== $extra)) {} // Bad x 4. + +if ((null !== $extra // Bad x 1. + && is_int($extra)) + && ($row->extra !== $extra // Bad x 1. + || $something) // Bad x 1. +) {} + +if ((null !== $extra) // Bad x 2. + && ($row->extra !== $extra) // Bad x 2. +) {} + +$a = (null !== $extra); +$a = (null !== $extra); // Bad x 2. + +$sx = $vert ? ($w - 1) : 0; + +$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} + +$directory = ('/' == $file[ strlen($file)-1 ]); + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if (( null !== $extra ) && ( $row->extra !== $extra )) {} // Bad x 4. + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} + +if (( null !== $extra // Bad x 1. + && is_int($extra) ) // Bad x 1. + && ( $row->extra !== $extra + || $something ) // Bad x 1. +) {} + +if (( null !== $extra ) // Bad x 2. + && ( $row->extra !== $extra ) // Bad x 2. +) {} + +$a = ( null !== $extra ); // Bad x 2. +$a = ( null !== $extra ); + +$sx = $vert ? ( $w - 1 ) : 0; // Bad x 2. + +$this->is_overloaded = ( ( ini_get("mbstring.func_overload") & 2 ) != 0 ) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 ); // Bad x 4. + +if ( $success && ( 'nothumb' == $target || 'all' == $target ) ) {} // Bad x 2. + +$directory = ( '/' == $file[ strlen($file)-1 ] ); // Bad x 2. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +/* + * Test handling of ignoreNewlines. + */ +if ( + (null !== $extra) && ($row->extra !== $extra) +) {} // Bad x 4, 1 x line 123, 2 x line 125, 1 x line 127. + + +$a = (null !== $extra); // Bad x 2, 1 x line 131, 1 x line 133. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ( + ( null !== $extra ) && ( $row->extra !== $extra ) +) {} // Bad x 4, 1 x line 137, 2 x line 139, 1 x line 141. + +$a = ( null !== $extra ); // Bad x 2, 1 x line 144, 1 x line 146. +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines true +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} + +$a = ( + null !== $extra +); +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines false + +if (true) {} (1+2) === 3 ? $a = 1 : $a = 2; +class A {} (1+2) === 3 ? $a = 1 : $a = 2; +function foo() {} (1+2) === 3 ? $a = 1 : $a = 2; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php new file mode 100644 index 000000000..0f70e287a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ArbitraryParenthesesSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 64 => 4, + 66 => 1, + 68 => 1, + 69 => 1, + 72 => 2, + 73 => 2, + 77 => 2, + 81 => 4, + 90 => 4, + 94 => 1, + 95 => 1, + 97 => 1, + 100 => 2, + 101 => 2, + 104 => 2, + 107 => 2, + 109 => 4, + 111 => 4, + 113 => 2, + 115 => 2, + 123 => 1, + 125 => 2, + 127 => 1, + 131 => 1, + 133 => 1, + 137 => 1, + 139 => 2, + 141 => 1, + 144 => 1, + 146 => 1, + 163 => 1, + 164 => 1, + 165 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 55 => 1, + 56 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc new file mode 100644 index 000000000..1826b585b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc @@ -0,0 +1,118 @@ +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
+
+
+
+
+
+ + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
+
+
+
+
+
+ + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
+
+
+
+
+
+ + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
+
+
+
+
+
+ + + + + + + Foo + + +
+
+
+
+
+
+ + + + + + + Foo + + +
+
+
+
+
+
+ + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowSpaceIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'DisallowSpaceIndentUnitTest.2.inc') { + return; + } + + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowSpaceIndentUnitTest.1.inc') + { + switch ($testFile) { + case 'DisallowSpaceIndentUnitTest.1.inc': + case 'DisallowSpaceIndentUnitTest.2.inc': + return [ + 5 => 1, + 9 => 1, + 15 => 1, + 22 => 1, + 24 => 1, + 30 => 1, + 35 => 1, + 50 => 1, + 55 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 73 => 1, + 77 => 1, + 81 => 1, + 104 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 108 => 1, + 110 => 1, + 111 => 1, + 112 => 1, + 114 => 1, + 115 => 1, + 117 => 1, + 118 => 1, + ]; + break; + case 'DisallowSpaceIndentUnitTest.3.inc': + return [ + 2 => 1, + 5 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + ]; + break; + case 'DisallowSpaceIndentUnitTest.js': + return [3 => 1]; + break; + case 'DisallowSpaceIndentUnitTest.css': + return [2 => 1]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc new file mode 100644 index 000000000..cf61177e8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc @@ -0,0 +1,93 @@ + 'Czech republic', + 'România' => 'Romania', + 'Magyarország' => 'Hungary', +); + +$var = "$hello $there"; + +?> + + + Foo + + +
+
+
+
+
+
+ + + + 'Czech republic', + 'România' => 'Romania', + 'Magyarország' => 'Hungary', +); + +$var = "$hello $there"; + +?> + + + Foo + + +
+
+
+
+
+
+ + + + + + + Foo + + +
+
+
+
+
+
+ + + + + + + Foo + + +
+
+
+
+
+
+ + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowTabIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowTabIndentUnitTest.1.inc': + return [ + 5 => 2, + 9 => 1, + 15 => 1, + 20 => 2, + 21 => 1, + 22 => 2, + 23 => 1, + 24 => 2, + 31 => 1, + 32 => 2, + 33 => 2, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 48 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 85 => 1, + 86 => 1, + 87 => 1, + 89 => 1, + 90 => 1, + 92 => 1, + 93 => 1, + ]; + break; + case 'DisallowTabIndentUnitTest.2.inc': + return [ + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 19 => 1, + ]; + break; + case 'DisallowTabIndentUnitTest.js': + return [ + 3 => 1, + 5 => 1, + 6 => 1, + ]; + break; + case 'DisallowTabIndentUnitTest.css': + return [ + 1 => 1, + 2 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc new file mode 100644 index 000000000..22c611be9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc @@ -0,0 +1,17 @@ + + * @copyright 2018 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncrementDecrementSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='IncrementDecrementSpacingUnitTest.inc') + { + switch ($testFile) { + case 'IncrementDecrementSpacingUnitTest.inc': + case 'IncrementDecrementSpacingUnitTest.js': + return [ + 5 => 1, + 6 => 1, + 8 => 1, + 10 => 1, + 13 => 1, + 14 => 1, + 16 => 1, + 17 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc new file mode 100644 index 000000000..505cb6e40 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc @@ -0,0 +1,79 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 30 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 38 => 1, + 44 => 1, + 45 => 1, + 46 => 2, + 49 => 1, + 51 => 1, + 59 => 1, + 61 => 1, + 63 => 1, + 67 => 1, + 70 => 1, + 71 => 1, + 75 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc new file mode 100644 index 000000000..caeb503aa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false + +hello(); + } + + function hello() + { + echo 'hello'; +}//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
+
+
+validate()) {
+    $safe = $form->getSubmitValues();
+}
+?>
+
+open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
+ +
+
+ +
+
+ +
+ + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
+
+
+ +
+
+
+ + +

some text

+ function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
+
+
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

+ self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): +if ($bar) $foo = 1; +elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
+ +
+ bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { +if (false) { +echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( +'some long description', function () { + }); +} + +switch ( $a ) { +case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'b': + $b = 3; +?> + + + + + +
+ +
+ +
+ +
+ + +
+ + + +
+ [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, +false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => +$value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed new file mode 100644 index 000000000..6fd9e5fd3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false + +hello(); + } + + function hello() + { + echo 'hello'; + }//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
+
+
+validate()) {
+    $safe = $form->getSubmitValues();
+}
+?>
+
+open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
+ +
+
+ +
+
+ +
+ + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
+
+
+ +
+
+
+ + +

some text

+ function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
+
+
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

+ self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
+ +
+ bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { + if (false) { + echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( + 'some long description', function () { + }); +} + +switch ( $a ) { + case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'b': + $b = 3; + ?> + + + + + +
+ +
+ +
+ +
+ + +
+ + + +
+ [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => + $value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js new file mode 100644 index 000000000..2195bfb9b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js @@ -0,0 +1,239 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +var script = document.createElement('script'); +script.onload = function() +{ + clearTimeout(t); + script456.onload = null; + script.onreadystatechange = null; + callback.call(this); + +}; + +this.callbacks[type] = { + namespaces: {}, +others: [] +}; + +blah = function() +{ + print something; + + } + +test(blah, function() { + print something; +}); + +var test = [{x: 10}]; +var test = [{ + x: 10, + y: { + b14h: 12, + 'b14h': 12 + }, + z: 23 +}]; + +Viper.prototype = { + + _removeEvents: function(elem) + { + if (!elem) { + elem = this.element; + } + + ViperUtil.removeEvent(elem, '.' + this.getEventNamespace()); + + } + +}; + +this.init = function(data) { + if (_pageListWdgt) { + GUI.getWidget('changedPagesList').addItemClickedCallback( + function(itemid, target) { + draftChangeTypeClicked( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + } + ); + } + ); + }//end if + +}; + +a( + function() { + var _a = function() { + b = false; + + }; + true + } +); + +(function() { + a = function() { + a(function() { + if (true) { + a = true; + } + }); + + a( + function() { + if (true) { + if (true) { + a = true; + } + } + } + ); + + a( + function() { + if (true) { + a = true; + } + } + ); + + }; + +})(); + +a.prototype = { + + a: function() + { + var currentSize = null; + ViperUtil.addEvent( + header, + 'safedblclick', + function() {}, + ); + + if (topContent) { + ViperUtil.addClass(topContent, 'Viper-popup-top'); + main.appendChild(topContent); + } + + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + } + +}; + +a.prototype = { + + a: function() + { + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + + var mouseUpAction = function() {}; + var preventMouseUp = false; + var self = this; + if (clickAction) { + } + } + +}; + +a.prototype = { + + a: function() + { + var a = function() { + var a = 'foo'; + }; + + if (true) { + } + + }, + + b: function() + { + ViperUtil.addEvent( + function() { + if (fullScreen !== true) { + currentSize = { + }; + + showfullScreen(); + } + } + ); + + }, + + c: function() + { + this.a( + { + a: function() { + form.onsubmit = function() { + return false; + }; + + var a = true; + } + } + ); + + } + +}; + +a.prototype = { + init: function() + {}, + + _b: function() + { + } + +}; + +for (var i = 0; i < 10; i++) { + var foo = {foo:{'a':'b', + 'c':'d'}}; +} + +class TestOk +{ + destroy() + { + setTimeout(a, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +class TestBad +{ + destroy() + { + setTimeout(function () { + return; + }, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +( function( $ ) { + foo(function( value ) { + value.bind( function( newval ) { + $( '#bar' ).html( newval ); + } ); + } )( jQuery ); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed new file mode 100644 index 000000000..d4bf409bc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed @@ -0,0 +1,239 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +var script = document.createElement('script'); +script.onload = function() +{ + clearTimeout(t); + script456.onload = null; + script.onreadystatechange = null; + callback.call(this); + +}; + +this.callbacks[type] = { + namespaces: {}, + others: [] +}; + +blah = function() +{ + print something; + +} + +test(blah, function() { + print something; +}); + +var test = [{x: 10}]; +var test = [{ + x: 10, + y: { + b14h: 12, + 'b14h': 12 + }, + z: 23 +}]; + +Viper.prototype = { + + _removeEvents: function(elem) + { + if (!elem) { + elem = this.element; + } + + ViperUtil.removeEvent(elem, '.' + this.getEventNamespace()); + + } + +}; + +this.init = function(data) { + if (_pageListWdgt) { + GUI.getWidget('changedPagesList').addItemClickedCallback( + function(itemid, target) { + draftChangeTypeClicked( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + } + ); + } + ); + }//end if + +}; + +a( + function() { + var _a = function() { + b = false; + + }; + true + } +); + +(function() { + a = function() { + a(function() { + if (true) { + a = true; + } + }); + + a( + function() { + if (true) { + if (true) { + a = true; + } + } + } + ); + + a( + function() { + if (true) { + a = true; + } + } + ); + + }; + +})(); + +a.prototype = { + + a: function() + { + var currentSize = null; + ViperUtil.addEvent( + header, + 'safedblclick', + function() {}, + ); + + if (topContent) { + ViperUtil.addClass(topContent, 'Viper-popup-top'); + main.appendChild(topContent); + } + + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + } + +}; + +a.prototype = { + + a: function() + { + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + + var mouseUpAction = function() {}; + var preventMouseUp = false; + var self = this; + if (clickAction) { + } + } + +}; + +a.prototype = { + + a: function() + { + var a = function() { + var a = 'foo'; + }; + + if (true) { + } + + }, + + b: function() + { + ViperUtil.addEvent( + function() { + if (fullScreen !== true) { + currentSize = { + }; + + showfullScreen(); + } + } + ); + + }, + + c: function() + { + this.a( + { + a: function() { + form.onsubmit = function() { + return false; + }; + + var a = true; + } + } + ); + + } + +}; + +a.prototype = { + init: function() + {}, + + _b: function() + { + } + +}; + +for (var i = 0; i < 10; i++) { + var foo = {foo:{'a':'b', + 'c':'d'}}; +} + +class TestOk +{ + destroy() + { + setTimeout(a, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +class TestBad +{ + destroy() + { + setTimeout(function () { + return; + }, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +( function( $ ) { + foo(function( value ) { + value.bind( function( newval ) { + $( '#bar' ).html( newval ); + } ); + } )( jQuery ); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc new file mode 100644 index 000000000..b8bf72ad5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent true + +hello(); + } + + function hello() + { + echo 'hello'; +}//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
+
+
+validate()) {
+	$safe = $form->getSubmitValues();
+}
+?>
+
+open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
+ +
+
+ +
+
+ +
+ + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
+
+
+ +
+
+
+ + +

some text

+ function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
+
+
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

+ self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): +if ($bar) $foo = 1; +elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
+ +
+ bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { +if (false) { +echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( +'some long description', function () { + }); +} + +switch ( $a ) { +case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'b': + $b = 3; +?> + + + + + +
+ +
+ +
+ +
+ + +
+ + + +
+ [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, +false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => +$value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed new file mode 100644 index 000000000..83324391d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed @@ -0,0 +1,1611 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent true + +hello(); + } + + function hello() + { + echo 'hello'; + }//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
+
+
+validate()) {
+	$safe = $form->getSubmitValues();
+}
+?>
+
+open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
+ +
+
+ +
+
+ +
+ + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
+
+
+ +
+
+
+ + +

some text

+ function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
+
+
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ 1) { + echo '1'; + } + ?> +
+ +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

+ self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
+ +
+ bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { + if (false) { + echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( + 'some long description', function () { + }); +} + +switch ( $a ) { + case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'b': + $b = 3; + ?> + + + + + +
+ +
+ +
+ +
+ + +
+ + + +
+ [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => + $value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc new file mode 100644 index 000000000..55d1a06ab --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc @@ -0,0 +1,28 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +phpcs:set Generic.WhiteSpace.ScopeIndent exact true + $enabled, + 'compression' => $compression, + ] = $options; +} + +$this->foo() + ->bar() + ->baz(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed new file mode 100644 index 000000000..e9ae5ff39 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed @@ -0,0 +1,28 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +phpcs:set Generic.WhiteSpace.ScopeIndent exact true + $enabled, + 'compression' => $compression, + ] = $options; +} + +$this->foo() + ->bar() + ->baz(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc new file mode 100644 index 000000000..e58dc4de7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc @@ -0,0 +1,6 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + // Tab width setting is only needed for the tabbed file. + if ($testFile === 'ScopeIndentUnitTest.2.inc') { + $config->tabWidth = 4; + } else { + $config->tabWidth = 0; + } + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ScopeIndentUnitTest.inc') + { + if ($testFile === 'ScopeIndentUnitTest.1.js') { + return [ + 6 => 1, + 14 => 1, + 21 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 39 => 1, + 42 => 1, + 59 => 1, + 60 => 1, + 75 => 1, + 120 => 1, + 121 => 1, + 122 => 1, + 123 => 1, + 141 => 1, + 142 => 1, + 155 => 1, + 156 => 1, + 168 => 1, + 184 => 1, + ]; + }//end if + + if ($testFile === 'ScopeIndentUnitTest.3.inc') { + return [ + 6 => 1, + 7 => 1, + 10 => 1, + ]; + } + + if ($testFile === 'ScopeIndentUnitTest.4.inc') { + return []; + } + + return [ + 7 => 1, + 10 => 1, + 13 => 1, + 17 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 58 => 1, + 123 => 1, + 224 => 1, + 225 => 1, + 279 => 1, + 280 => 1, + 281 => 1, + 282 => 1, + 283 => 1, + 284 => 1, + 285 => 1, + 286 => 1, + 336 => 1, + 349 => 1, + 380 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 389 => 1, + 390 => 1, + 397 => 1, + 419 => 1, + 420 => 1, + 465 => 1, + 467 => 1, + 472 => 1, + 473 => 1, + 474 => 1, + 496 => 1, + 498 => 1, + 500 => 1, + 524 => 1, + 526 => 1, + 544 => 1, + 545 => 1, + 546 => 1, + 639 => 1, + 660 => 1, + 662 => 1, + 802 => 1, + 803 => 1, + 823 => 1, + 858 => 1, + 879 => 1, + 1163 => 1, + 1197 => 1, + 1198 => 1, + 1259 => 1, + 1264 => 1, + 1265 => 1, + 1266 => 1, + 1269 => 1, + 1272 => 1, + 1273 => 1, + 1274 => 1, + 1275 => 1, + 1276 => 1, + 1277 => 1, + 1280 => 1, + 1281 => 1, + 1282 => 1, + 1284 => 1, + 1285 => 1, + 1288 => 1, + 1289 => 1, + 1290 => 1, + 1292 => 1, + 1293 => 1, + 1310 => 1, + 1312 => 1, + 1327 => 1, + 1328 => 1, + 1329 => 1, + 1330 => 1, + 1331 => 1, + 1332 => 1, + 1335 => 1, + 1340 => 1, + 1342 => 1, + 1345 => 1, + 1488 => 1, + 1489 => 1, + 1500 => 1, + 1503 => 1, + 1518 => 1, + 1520 => 1, + 1527 => 1, + 1529 => 1, + 1530 => 1, + 1583 => 1, + 1584 => 1, + 1585 => 1, + 1586 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc new file mode 100644 index 000000000..edce4dcc6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.inc @@ -0,0 +1,73 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SpreadOperatorSpacingAfterUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 20 => 2, + 40 => 1, + 41 => 1, + 46 => 2, + 60 => 1, + 61 => 1, + 66 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml new file mode 100644 index 000000000..728426e6a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml @@ -0,0 +1,4 @@ + + + A collection of generic sniffs. This standard is not designed to be used to check code. + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php new file mode 100644 index 000000000..9575398aa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\CSS; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class BrowserSpecificStylesSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of specific stylesheet suffixes we allow. + * + * These stylesheets contain browser specific styles + * so this sniff ignore them files in the form: + * *_moz.css and *_ie7.css etc. + * + * @var array + */ + protected $specificStylesheets = [ + 'moz' => true, + 'ie' => true, + 'ie7' => true, + 'ie8' => true, + 'webkit' => true, + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Ignore files with browser-specific suffixes. + $filename = $phpcsFile->getFilename(); + $breakChar = strrpos($filename, '_'); + if ($breakChar !== false && substr($filename, -4) === '.css') { + $specific = substr($filename, ($breakChar + 1), -4); + if (isset($this->specificStylesheets[$specific]) === true) { + return; + } + } + + $tokens = $phpcsFile->getTokens(); + $content = $tokens[$stackPtr]['content']; + + if ($content[0] === '-') { + $error = 'Browser-specific styles are not allowed'; + $phpcsFile->addError($error, $stackPtr, 'ForbiddenStyle'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php new file mode 100644 index 000000000..81b7f1b69 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php @@ -0,0 +1,125 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowSelfActionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We are not interested in abstract classes. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['code'] === T_ABSTRACT) { + return; + } + + // We are only interested in Action classes. + $classNameToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $className = $tokens[$classNameToken]['content']; + if (substr($className, -7) !== 'Actions') { + return; + } + + $foundFunctions = []; + $foundCalls = []; + + // Find all static method calls in the form self::method() in the class. + $classEnd = $tokens[$stackPtr]['scope_closer']; + for ($i = ($classNameToken + 1); $i < $classEnd; $i++) { + if ($tokens[$i]['code'] !== T_DOUBLE_COLON) { + if ($tokens[$i]['code'] === T_FUNCTION) { + // Cache the function information. + $funcName = $phpcsFile->findNext(T_STRING, ($i + 1)); + $funcScope = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($i - 1)); + + $foundFunctions[$tokens[$funcName]['content']] = strtolower($tokens[$funcScope]['content']); + } + + continue; + } + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($tokens[$prevToken]['content'] !== 'self' + && $tokens[$prevToken]['content'] !== 'static' + ) { + continue; + } + + $funcNameToken = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$funcNameToken]['code'] === T_VARIABLE) { + // We are only interested in function calls. + continue; + } + + $funcName = $tokens[$funcNameToken]['content']; + + // We've found the function, now we need to find it and see if it is + // public, private or protected. If it starts with an underscore we + // can assume it is private. + if ($funcName[0] === '_') { + continue; + } + + $foundCalls[$i] = [ + 'name' => $funcName, + 'type' => strtolower($tokens[$prevToken]['content']), + ]; + }//end for + + $errorClassName = substr($className, 0, -7); + + foreach ($foundCalls as $token => $funcData) { + if (isset($foundFunctions[$funcData['name']]) === false) { + // Function was not in this class, might have come from the parent. + // Either way, we can't really check this. + continue; + } else if ($foundFunctions[$funcData['name']] === 'public') { + $type = $funcData['type']; + $error = "Static calls to public methods in Action classes must not use the $type keyword; use %s::%s() instead"; + $data = [ + $errorClassName, + $funcName, + ]; + $phpcsFile->addError($error, $token, 'Found'.ucfirst($funcData['type']), $data); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php new file mode 100644 index 000000000..2d56261cf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class IncludeOwnSystemSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $fileName = $phpcsFile->getFilename(); + $matches = []; + if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|i', $fileName, $matches) === 0) { + // Not an actions file. + return; + } + + $ownClass = $matches[2]; + $tokens = $phpcsFile->getTokens(); + + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 2), null, false, true); + $typeName = trim($tokens[$typeName]['content'], " '"); + switch (strtolower($tokens[($stackPtr + 1)]['content'])) { + case 'includesystem' : + $included = strtolower($typeName); + break; + case 'includeasset' : + $included = strtolower($typeName).'assettype'; + break; + case 'includewidget' : + $included = strtolower($typeName).'widgettype'; + break; + default: + return; + } + + if ($included === strtolower($ownClass)) { + $error = "You do not need to include \"%s\" from within the system's own actions file"; + $data = [$ownClass]; + $phpcsFile->addError($error, $stackPtr, 'NotRequired', $data); + } + + }//end process() + + + /** + * Determines the included class name from given token. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param array $tokens The array of file tokens. + * @param int $stackPtr The position in the tokens array of the + * potentially included class. + * + * @return string + */ + protected function getIncludedClassFromToken( + $phpcsFile, + array $tokens, + $stackPtr + ) { + + return false; + + }//end getIncludedClassFromToken() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php new file mode 100644 index 000000000..8bbd91e82 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php @@ -0,0 +1,314 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class IncludeSystemSniff extends AbstractScopeSniff +{ + + /** + * A list of classes that don't need to be included. + * + * @var string[] + */ + private $ignore = [ + 'self' => true, + 'static' => true, + 'parent' => true, + 'channels' => true, + 'basesystem' => true, + 'dal' => true, + 'init' => true, + 'pdo' => true, + 'util' => true, + 'ziparchive' => true, + 'phpunit_framework_assert' => true, + 'abstractmysourceunittest' => true, + 'abstractdatacleanunittest' => true, + 'exception' => true, + 'abstractwidgetwidgettype' => true, + 'domdocument' => true, + ]; + + + /** + * Constructs an AbstractScopeSniff. + */ + public function __construct() + { + parent::__construct([T_FUNCTION], [T_DOUBLE_COLON, T_EXTENDS], true); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param integer $stackPtr The position where the token was found. + * @param integer $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine the name of the class that the static function + // is being called on. + $classNameToken = $phpcsFile->findPrevious( + T_WHITESPACE, + ($stackPtr - 1), + null, + true + ); + + // Don't process class names represented by variables as this can be + // an inexact science. + if ($tokens[$classNameToken]['code'] === T_VARIABLE) { + return; + } + + $className = $tokens[$classNameToken]['content']; + if (isset($this->ignore[strtolower($className)]) === true) { + return; + } + + $includedClasses = []; + + $fileName = strtolower($phpcsFile->getFilename()); + $matches = []; + if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) { + // This is an actions file, which means we don't + // have to include the system in which it exists. + $includedClasses[$matches[2]] = true; + + // Or a system it implements. + $class = $phpcsFile->getCondition($stackPtr, T_CLASS); + $implements = $phpcsFile->findNext(T_IMPLEMENTS, $class, ($class + 10)); + if ($implements !== false) { + $implementsClass = $phpcsFile->findNext(T_STRING, $implements); + $implementsClassName = strtolower($tokens[$implementsClass]['content']); + if (substr($implementsClassName, -7) === 'actions') { + $includedClasses[substr($implementsClassName, 0, -7)] = true; + } + } + } + + // Go searching for includeSystem and includeAsset calls within this + // function, or the inclusion of .inc files, which + // would be library files. + for ($i = ($currScope + 1); $i < $stackPtr; $i++) { + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + // Special case for Widgets cause they are, well, special. + } else if (strtolower($tokens[$i]['content']) === 'includewidget') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + $includedClasses[strtolower($typeName).'widgettype'] = true; + } + } + + // Now go searching for includeSystem, includeAsset or require/include + // calls outside our scope. If we are in a class, look outside the + // class. If we are not, look outside the function. + $condPtr = $currScope; + if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) { + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) { + if ($condType === T_CLASS) { + break; + } + } + } + + for ($i = 0; $i < $condPtr; $i++) { + // Skip other scopes. + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + } + } + + // If we are in a testing class, we might have also included + // some systems and classes in our setUp() method. + $setupFunction = null; + if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) { + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) { + if ($condType === T_CLASS) { + // Is this is a testing class? + $name = $phpcsFile->findNext(T_STRING, $condPtr); + $name = $tokens[$name]['content']; + if (substr($name, -8) === 'UnitTest') { + // Look for a method called setUp(). + $end = $tokens[$condPtr]['scope_closer']; + $function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end); + while ($function !== false) { + $name = $phpcsFile->findNext(T_STRING, $function); + if ($tokens[$name]['content'] === 'setUp') { + $setupFunction = $function; + break; + } + + $function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end); + } + } + } + }//end foreach + }//end if + + if ($setupFunction !== null) { + $start = ($tokens[$setupFunction]['scope_opener'] + 1); + $end = $tokens[$setupFunction]['scope_closer']; + for ($i = $start; $i < $end; $i++) { + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + } + } + }//end if + + if (isset($includedClasses[strtolower($className)]) === false) { + $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token within the scope that this test is listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * this token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_EXTENDS) { + // Find the class name. + $classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1)); + $className = $tokens[$classNameToken]['content']; + } else { + // Determine the name of the class that the static function + // is being called on. But don't process class names represented by + // variables as this can be an inexact science. + $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$classNameToken]['code'] === T_VARIABLE) { + return; + } + + $className = $tokens[$classNameToken]['content']; + } + + // Some systems are always available. + if (isset($this->ignore[strtolower($className)]) === true) { + return; + } + + $includedClasses = []; + + $fileName = strtolower($phpcsFile->getFilename()); + $matches = []; + if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) { + // This is an actions file, which means we don't + // have to include the system in which it exists + // We know the system from the path. + $includedClasses[$matches[1]] = true; + } + + // Go searching for includeSystem, includeAsset or require/include + // calls outside our scope. + for ($i = 0; $i < $stackPtr; $i++) { + // Skip classes and functions as will we never get + // into their scopes when including this file, although + // we have a chance of getting into IF, WHILE etc. + if (($tokens[$i]['code'] === T_CLASS + || $tokens[$i]['code'] === T_INTERFACE + || $tokens[$i]['code'] === T_FUNCTION) + && isset($tokens[$i]['scope_closer']) === true + ) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + // Special case for Widgets cause they are, well, special. + } else if (strtolower($tokens[$i]['content']) === 'includewidget') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + $includedClasses[strtolower($typeName).'widgettype'] = true; + } + }//end for + + if (isset($includedClasses[strtolower($className)]) === false) { + if ($tokens[$stackPtr]['code'] === T_EXTENDS) { + $error = 'Class extends non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedExtends', $data); + } else { + $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data); + } + } + + }//end processTokenOutsideScope() + + + /** + * Determines the included class name from given token. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param array $tokens The array of file tokens. + * @param int $stackPtr The position in the tokens array of the + * potentially included class. + * + * @return string + */ + protected function getIncludedClassFromToken(File $phpcsFile, array $tokens, $stackPtr) + { + if (strtolower($tokens[$stackPtr]['content']) === 'includesystem') { + $systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $systemName = trim($tokens[$systemName]['content'], " '"); + return strtolower($systemName); + } else if (strtolower($tokens[$stackPtr]['content']) === 'includeasset') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + return strtolower($typeName).'assettype'; + } else if (isset(Tokens::$includeTokens[$tokens[$stackPtr]['code']]) === true) { + $filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $filePath = $tokens[$filePath]['content']; + $filePath = trim($filePath, " '"); + $filePath = basename($filePath, '.inc'); + return strtolower($filePath); + } + + return false; + + }//end getIncludedClassFromToken() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php new file mode 100644 index 000000000..6b10cd3ed --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class UnusedSystemSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check if this is a call to includeSystem, includeAsset or includeWidget. + $methodName = strtolower($tokens[($stackPtr + 1)]['content']); + if ($methodName === 'includesystem' + || $methodName === 'includeasset' + || $methodName === 'includewidget' + ) { + $systemName = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 3), null, true); + if ($systemName === false || $tokens[$systemName]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + // Must be using a variable instead of a specific system name. + // We can't accurately check that. + return; + } + + $systemName = trim($tokens[$systemName]['content'], " '"); + } else { + return; + } + + if ($methodName === 'includeasset') { + $systemName .= 'assettype'; + } else if ($methodName === 'includewidget') { + $systemName .= 'widgettype'; + } + + $systemName = strtolower($systemName); + + // Now check if this system is used anywhere in this scope. + $level = $tokens[$stackPtr]['level']; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['level'] < $level) { + // We have gone out of scope. + // If the original include was inside an IF statement that + // is checking if the system exists, check the outer scope + // as well. + if ($tokens[$stackPtr]['level'] === $level) { + // We are still in the base level, so this is the first + // time we have got here. + $conditions = array_keys($tokens[$stackPtr]['conditions']); + if (empty($conditions) === false) { + $cond = array_pop($conditions); + if ($tokens[$cond]['code'] === T_IF) { + $i = $tokens[$cond]['scope_closer']; + $level--; + continue; + } + } + } + + break; + }//end if + + if ($tokens[$i]['code'] !== T_DOUBLE_COLON + && $tokens[$i]['code'] !== T_EXTENDS + && $tokens[$i]['code'] !== T_IMPLEMENTS + ) { + continue; + } + + switch ($tokens[$i]['code']) { + case T_DOUBLE_COLON: + $usedName = strtolower($tokens[($i - 1)]['content']); + if ($usedName === $systemName) { + // The included system was used, so it is fine. + return; + } + break; + case T_EXTENDS: + $classNameToken = $phpcsFile->findNext(T_STRING, ($i + 1)); + $className = strtolower($tokens[$classNameToken]['content']); + if ($className === $systemName) { + // The included system was used, so it is fine. + return; + } + break; + case T_IMPLEMENTS: + $endImplements = $phpcsFile->findNext([T_EXTENDS, T_OPEN_CURLY_BRACKET], ($i + 1)); + for ($x = ($i + 1); $x < $endImplements; $x++) { + if ($tokens[$x]['code'] === T_STRING) { + $className = strtolower($tokens[$x]['content']); + if ($className === $systemName) { + // The included system was used, so it is fine. + return; + } + } + } + break; + }//end switch + }//end for + + // If we get to here, the system was not use. + $error = 'Included system "%s" is never used'; + $data = [$systemName]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 000000000..fd75bcb22 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,84 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Commenting; + +use PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FunctionCommentSniff as SquizFunctionCommentSniff; +use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Files\File; + +class FunctionCommentSniff extends SquizFunctionCommentSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + parent::process($phpcsFile, $stackPtr); + + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + $hasApiTag = false; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@api') { + if ($hasApiTag === true) { + // We've come across an API tag already, which means + // we were not the first tag in the API list. + $error = 'The @api tag must come first in the @api tag list in a function comment'; + $phpcsFile->addError($error, $tag, 'ApiNotFirst'); + } + + $hasApiTag = true; + + // There needs to be a blank line before the @api tag. + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], ($tag - 1)); + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 2)) { + $error = 'There must be one blank line before the @api tag in a function comment'; + $phpcsFile->addError($error, $tag, 'ApiSpacing'); + } + } else if (substr($tokens[$tag]['content'], 0, 5) === '@api-') { + $hasApiTag = true; + + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], ($tag - 1)); + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) { + $error = 'There must be no blank line before the @%s tag in a function comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addError($error, $tag, 'ApiTagSpacing', $data); + } + }//end if + }//end foreach + + if ($hasApiTag === true && substr($tokens[$tag]['content'], 0, 4) !== '@api') { + // API tags must be the last tags in a function comment. + $error = 'The @api tags must be the last tags in a function comment'; + $phpcsFile->addError($error, $commentEnd, 'ApiNotLast'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php new file mode 100644 index 000000000..eccf6fe4b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class DebugCodeSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if (strtolower($tokens[$className]['content']) === 'debug') { + $method = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $error = 'Call to debug function Debug::%s() must be removed'; + $data = [$tokens[$method]['content']]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php new file mode 100644 index 000000000..3115bac4e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class FirebugConsoleSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_PROPERTY, + T_LABEL, + T_OBJECT, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (strtolower($tokens[$stackPtr]['content']) === 'console') { + $error = 'Variables, functions and labels must not be named "console"; name may conflict with Firebug internal variable'; + $phpcsFile->addError($error, $stackPtr, 'ConflictFound'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php new file mode 100644 index 000000000..0a3c9cf21 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class AssignThisSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_THIS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore this.something and other uses of "this" that are not + // direct assignments. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] !== T_SEMICOLON) { + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + return; + } + } + + // Something must be assigned to "this". + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_EQUAL) { + return; + } + + // A variable needs to be assigned to "this". + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true); + if ($tokens[$prev]['code'] !== T_STRING) { + return; + } + + // We can only assign "this" to a var called "self". + if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') { + $error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"'; + $phpcsFile->addError($error, $prev, 'NotSelf'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php new file mode 100644 index 000000000..8fb893760 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php @@ -0,0 +1,218 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class CreateWidgetTypeCallbackSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OBJECT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findPrevious(T_STRING, ($stackPtr - 1)); + if (substr(strtolower($tokens[$className]['content']), -10) !== 'widgettype') { + return; + } + + // Search for a create method. + $create = $phpcsFile->findNext(T_PROPERTY, $stackPtr, $tokens[$stackPtr]['bracket_closer'], null, 'create'); + if ($create === false) { + return; + } + + $function = $phpcsFile->findNext([T_WHITESPACE, T_COLON], ($create + 1), null, true); + if ($tokens[$function]['code'] !== T_FUNCTION + && $tokens[$function]['code'] !== T_CLOSURE + ) { + return; + } + + $start = ($tokens[$function]['scope_opener'] + 1); + $end = ($tokens[$function]['scope_closer'] - 1); + + // Check that the first argument is called "callback". + $arg = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$function]['parenthesis_opener'] + 1), null, true); + if ($tokens[$arg]['content'] !== 'callback') { + $error = 'The first argument of the create() method of a widget type must be called "callback"'; + $phpcsFile->addError($error, $arg, 'FirstArgNotCallback'); + } + + /* + Look for return statements within the function. They cannot return + anything and must be preceded by the callback.call() line. The + callback itself must contain "self" or "this" as the first argument + and there needs to be a call to the callback function somewhere + in the create method. All calls to the callback function must be + followed by a return statement or the end of the method. + */ + + $foundCallback = false; + $passedCallback = false; + $nestedFunction = null; + for ($i = $start; $i <= $end; $i++) { + // Keep track of nested functions. + if ($nestedFunction !== null) { + if ($i === $nestedFunction) { + $nestedFunction = null; + continue; + } + } else if (($tokens[$i]['code'] === T_FUNCTION + || $tokens[$i]['code'] === T_CLOSURE) + && isset($tokens[$i]['scope_closer']) === true + ) { + $nestedFunction = $tokens[$i]['scope_closer']; + continue; + } + + if ($nestedFunction === null && $tokens[$i]['code'] === T_RETURN) { + // Make sure return statements are not returning anything. + if ($tokens[($i + 1)]['code'] !== T_SEMICOLON) { + $error = 'The create() method of a widget type must not return a value'; + $phpcsFile->addError($error, $i, 'ReturnValue'); + } + + continue; + } else if ($tokens[$i]['code'] !== T_STRING + || $tokens[$i]['content'] !== 'callback' + ) { + continue; + } + + // If this is the form "callback.call(" then it is a call + // to the callback function. + if ($tokens[($i + 1)]['code'] !== T_OBJECT_OPERATOR + || $tokens[($i + 2)]['content'] !== 'call' + || $tokens[($i + 3)]['code'] !== T_OPEN_PARENTHESIS + ) { + // One last chance; this might be the callback function + // being passed to another function, like this + // "this.init(something, callback, something)". + if (isset($tokens[$i]['nested_parenthesis']) === false) { + continue; + } + + // Just make sure those brackets don't belong to anyone, + // like an IF or FOR statement. + foreach ($tokens[$i]['nested_parenthesis'] as $bracket) { + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + continue(2); + } + } + + // Note that we use this endBracket down further when checking + // for a RETURN statement. + $nestedParens = $tokens[$i]['nested_parenthesis']; + $endBracket = end($nestedParens); + $bracket = key($nestedParens); + + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($bracket - 1), + null, + true + ); + + if ($tokens[$prev]['code'] !== T_STRING) { + // This is not a function passing the callback. + continue; + } + + $passedCallback = true; + }//end if + + $foundCallback = true; + + if ($passedCallback === false) { + // The first argument must be "this" or "self". + $arg = $phpcsFile->findNext(T_WHITESPACE, ($i + 4), null, true); + if ($tokens[$arg]['content'] !== 'this' + && $tokens[$arg]['content'] !== 'self' + ) { + $error = 'The first argument passed to the callback function must be "this" or "self"'; + $phpcsFile->addError($error, $arg, 'FirstArgNotSelf'); + } + } + + // Now it must be followed by a return statement or the end of the function. + if ($passedCallback === false) { + $endBracket = $tokens[($i + 3)]['parenthesis_closer']; + } + + for ($next = $endBracket; $next <= $end; $next++) { + // Skip whitespace so we find the next content after the call. + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true) { + continue; + } + + // Skip closing braces like END IF because it is not executable code. + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + continue; + } + + // We don't care about anything on the current line, like a + // semicolon. It doesn't matter if there are other statements on the + // line because another sniff will check for those. + if ($tokens[$next]['line'] === $tokens[$endBracket]['line']) { + continue; + } + + break; + } + + if ($next !== $tokens[$function]['scope_closer'] + && $tokens[$next]['code'] !== T_RETURN + ) { + $error = 'The call to the callback function must be followed by a return statement if it is not the last statement in the create() method'; + $phpcsFile->addError($error, $i, 'NoReturn'); + } + }//end for + + if ($foundCallback === false) { + $error = 'The create() method of a widget type must call the callback function'; + $phpcsFile->addError($error, $create, 'CallbackNotCalled'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php new file mode 100644 index 000000000..cae7c08d9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class DisallowNewWidgetSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$className]['code'] !== T_STRING) { + return; + } + + if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') { + $widgetType = substr($tokens[$className]['content'], 0, -10); + $error = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead'; + $data = [$widgetType]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php new file mode 100644 index 000000000..3914b7b8e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class AjaxNullComparisonSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure it is an API function. We know this by the doc comment. + $commentEnd = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr); + $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, ($commentEnd - 1)); + // If function doesn't contain any doc comments - skip it. + if ($commentEnd === false || $commentStart === false) { + return; + } + + $comment = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart)); + if (strpos($comment, '* @api') === false) { + return; + } + + // Find all the vars passed in as we are only interested in comparisons + // to NULL for these specific variables. + $foundVars = []; + $open = $tokens[$stackPtr]['parenthesis_opener']; + $close = $tokens[$stackPtr]['parenthesis_closer']; + for ($i = ($open + 1); $i < $close; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + $foundVars[$tokens[$i]['content']] = true; + } + } + + if (empty($foundVars) === true) { + return; + } + + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + for ($i = ($start + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE + || isset($foundVars[$tokens[$i]['content']]) === false + ) { + continue; + } + + $operator = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$operator]['code'] !== T_IS_IDENTICAL + && $tokens[$operator]['code'] !== T_IS_NOT_IDENTICAL + ) { + continue; + } + + $nullValue = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), null, true); + if ($tokens[$nullValue]['code'] !== T_NULL) { + continue; + } + + $error = 'Values submitted via Ajax requests should not be compared directly to NULL; use empty() instead'; + $phpcsFile->addWarning($error, $nullValue, 'Found'); + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php new file mode 100644 index 000000000..67b35723f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class EvalObjectFactorySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EVAL]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + /* + We need to find all strings that will be in the eval + to determine if the "new" keyword is being used. + */ + + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $strings = []; + $vars = []; + + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $strings[$i] = $tokens[$i]['content']; + } else if ($tokens[$i]['code'] === T_VARIABLE) { + $vars[$i] = $tokens[$i]['content']; + } + } + + /* + We now have some variables that we need to expand into + the strings that were assigned to them, if any. + */ + + foreach ($vars as $varPtr => $varName) { + while (($prev = $phpcsFile->findPrevious(T_VARIABLE, ($varPtr - 1))) !== false) { + // Make sure this is an assignment of the variable. That means + // it will be the first thing on the line. + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true); + if ($tokens[$prevContent]['line'] === $tokens[$prev]['line']) { + $varPtr = $prevContent; + continue; + } + + if ($tokens[$prev]['content'] !== $varName) { + // This variable has a different name. + $varPtr = $prevContent; + continue; + } + + // We found one. + break; + }//end while + + if ($prev !== false) { + // Find all strings on the line. + $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prev + 1)); + for ($i = ($prev + 1); $i < $lineEnd; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $strings[$i] = $tokens[$i]['content']; + } + } + } + }//end foreach + + foreach ($strings as $string) { + // If the string has "new" in it, it is not allowed. + // We don't bother checking if the word "new" is printed to screen + // because that is unlikely to happen. We assume the use + // of "new" is for object instantiation. + if (strstr($string, ' new ') !== false) { + $error = 'Do not use eval() to create objects dynamically; use reflection instead'; + $phpcsFile->addWarning($error, $stackPtr, 'Found'); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php new file mode 100644 index 000000000..82419fcb8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php @@ -0,0 +1,106 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class GetRequestDataSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_VARIABLE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $varName = $tokens[$stackPtr]['content']; + if ($varName !== '$_REQUEST' + && $varName !== '$_GET' + && $varName !== '$_POST' + && $varName !== '$_FILES' + ) { + return; + } + + // The only place these super globals can be accessed directly is + // in the getRequestData() method of the Security class. + $inClass = false; + foreach ($tokens[$stackPtr]['conditions'] as $i => $type) { + if ($tokens[$i]['code'] === T_CLASS) { + $className = $phpcsFile->findNext(T_STRING, $i); + $className = $tokens[$className]['content']; + if (strtolower($className) === 'security') { + $inClass = true; + } else { + // We don't have nested classes. + break; + } + } else if ($inClass === true && $tokens[$i]['code'] === T_FUNCTION) { + $funcName = $phpcsFile->findNext(T_STRING, $i); + $funcName = $tokens[$funcName]['content']; + if (strtolower($funcName) === 'getrequestdata') { + // This is valid. + return; + } else { + // We don't have nested functions. + break; + } + }//end if + }//end foreach + + // If we get to here, the super global was used incorrectly. + // First find out how it is being used. + $globalName = strtolower(substr($varName, 2)); + $usedVar = ''; + + $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$openBracket]['code'] === T_OPEN_SQUARE_BRACKET) { + $closeBracket = $tokens[$openBracket]['bracket_closer']; + $usedVar = $phpcsFile->getTokensAsString(($openBracket + 1), ($closeBracket - $openBracket - 1)); + } + + $type = 'SuperglobalAccessed'; + $error = 'The %s super global must not be accessed directly; use Security::getRequestData('; + $data = [$varName]; + if ($usedVar !== '') { + $type .= 'WithVar'; + $error .= '%s, \'%s\''; + $data[] = $usedVar; + $data[] = $globalName; + } + + $error .= ') instead'; + $phpcsFile->addError($error, $stackPtr, $type, $data); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php new file mode 100644 index 000000000..9b2029af4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class ReturnFunctionValueSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_RETURN]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $functionName = $phpcsFile->findNext(T_STRING, ($stackPtr + 1), null, false, null, true); + + while ($functionName !== false) { + // Check if this is really a function. + $bracket = $phpcsFile->findNext(T_WHITESPACE, ($functionName + 1), null, true); + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + $functionName = $phpcsFile->findNext(T_STRING, ($functionName + 1), null, false, null, true); + continue; + } + + $error = 'The result of a function call should be assigned to a variable before being returned'; + $phpcsFile->addWarning($error, $stackPtr, 'NotAssigned'); + break; + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php new file mode 100644 index 000000000..311cf684f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Strings; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class JoinStringsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'] !== 'join') { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_SQUARE_BRACKET) { + $opener = $tokens[$prev]['bracket_opener']; + if ($tokens[($opener - 1)]['code'] !== T_STRING) { + // This means the array is declared inline, like x = [a,b,c].join() + // and not elsewhere, like x = y[a].join() + // The first is not allowed while the second is. + $error = 'Joining strings using inline arrays is not allowed; use the + operator instead'; + $phpcsFile->addError($error, $stackPtr, 'ArrayNotAllowed'); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css new file mode 100644 index 000000000..339ee1544 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css @@ -0,0 +1,13 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + line-height: -25px; + cursor: pointer; + -moz-user-select: none; +} + +.AssetLineageWidgetType-item { + float: left; + list-style: none; + height: 22px; + cursor: pointer; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php new file mode 100644 index 000000000..213534998 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class BrowserSpecificStylesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [5 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc new file mode 100644 index 000000000..95fd04b79 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc @@ -0,0 +1,51 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php new file mode 100644 index 000000000..d29bf5c6c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowSelfActionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 28 => 1, + 29 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc new file mode 100644 index 000000000..ccb0273e0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc @@ -0,0 +1,112 @@ +fetch(PDO::FETCH_NUM) +BaseSystem::getDataDir(); +Util::getArrayIndex(array(), ''); + + +Channels::includeSystem('Widget'); +Widget::includeWidget('AbstractContainer'); +class MyWidget extends AbstractContainerWidgetType {} +class MyOtherWidget extends BookWidgetType {} + +$zip = new ZipArchive(); +$res = $zip->open($path, ZipArchive::CREATE); + +class AssetListingUnitTest extends AbstractMySourceUnitTest +{ + function setUp() { + parent::setUp(); + Channels::includeSystem('MySystem2'); + include_once 'Libs/FileSystem.inc'; + } + + function two() { + $siteid = MySystem2::getCurrentSiteId(); + $parserFiles = FileSystem::listDirectory(); + } + + function three() { + $siteid = MySystem3::getCurrentSiteId(); + $parserFiles = FileSystem::listDirectory(); + } +} + +if (Channels::systemExists('Log') === TRUE) { + Channels::includeSystem('Log'); +} else { + return; +} + +Log::addProjectLog('metadata.field.update', $msg); + +function two() { + Widget::includeWidget('CacheAdminScreen'); + $barChart = CacheAdminScreenWidgetType::constructBarchart($data); +} + +$adjustDialog->setOrientation(AbstractWidgetWidgetType::CENTER); + +$className = 'SquizPerspective'.ucfirst($property['type']).'PropertyType'; +Channels::includeSystem($className); +$className::setValue($assetid, $propertyid, $perspectives, $value, (array) $property['settings']); +?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php new file mode 100644 index 000000000..0320038ec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncludeSystemUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 14 => 1, + 24 => 1, + 27 => 1, + 28 => 1, + 31 => 1, + 36 => 1, + 41 => 1, + 61 => 1, + 70 => 1, + 89 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc new file mode 100644 index 000000000..c7bd4738f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc @@ -0,0 +1,67 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php new file mode 100644 index 000000000..fbc0ac70b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UnusedSystemUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 8 => 1, + 24 => 1, + 34 => 1, + 54 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 000000000..19d5c5d4c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,101 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 000000000..5cc43b644 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 28 => 1, + 36 => 1, + 37 => 2, + 49 => 1, + 58 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc new file mode 100644 index 000000000..349016101 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc @@ -0,0 +1,4 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php new file mode 100644 index 000000000..78da9c94f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DebugCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js new file mode 100644 index 000000000..d5e3df571 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js @@ -0,0 +1,8 @@ +console.info(); +console.warn(); +console.test(); +con.sole(); +var console = { + console: 'string'; +}; +function console() {} \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php new file mode 100644 index 000000000..3a9c23584 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FirebugConsoleUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FirebugConsoleUnitTest.js') + { + if ($testFile !== 'FirebugConsoleUnitTest.js') { + return []; + } + + return [ + 1 => 1, + 2 => 1, + 3 => 1, + 5 => 1, + 6 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js new file mode 100644 index 000000000..747a10084 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js @@ -0,0 +1,20 @@ +var self = this; +buttonWidget.addClickEvent(function() { + self.addDynamicSouce(); +}); + +var x = self; +var y = this; + +var test = ''; +if (true) { + test = this +} + +var itemid = this.items[i].getAttribute('itemid'); + +for (var x = this; y < 10; y++) { + var x = this + 1; +} + +var _self = this; \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php new file mode 100644 index 000000000..f28dff191 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class AssignThisUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='AssignThisUnitTest.js') + { + if ($testFile !== 'AssignThisUnitTest.js') { + return []; + } + + return [ + 7 => 1, + 11 => 1, + 16 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js new file mode 100644 index 000000000..22822d321 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js @@ -0,0 +1,186 @@ +SampleWidgetType.prototype = { + + create: function(callback) + { + if (x === 1) { + return; + } + + if (y === 1) { + callback.call(this); + // A comment here to explain the return is okay. + return; + } + + if (a === 1) { + // Cant return value even after calling callback. + callback.call(this); + return something; + } + + if (a === 1) { + // Need to pass self or this to callback function. + callback.call(a); + } + + callback.call(self); + + var self = this; + this.createChildren(null, function() { + callback.call(self, div); + }); + + // Never good to return a value. + return something; + + callback.call(self); + } + +}; + +AnotherSampleWidgetType.prototype = { + + create: function(input) + { + return; + } + + getSomething: function(input) + { + return 1; + } + +}; + + +NoCreateWidgetType.prototype = { + + getSomething: function(input) + { + return; + } + +}; + + +SomeRandom.prototype = { + + create: function(input) + { + return; + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (a === 1) { + // This is ok because it is the last statement, + // even though it is conditional. + callback.call(self); + } + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + var something = callback; + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + // Also valid because we are passing the callback to + // someone else to call. + if (y === 1) { + this.something(callback); + return; + } + + this.init(callback); + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + // Also valid because we are passing the callback to + // someone else to call. + if (y === 1) { + this.something(callback); + } + + this.init(callback); + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (a === 1) { + // This is ok because it is the last statement, + // even though it is conditional. + this.something(callback); + } + + } + +}; + + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (dfx.isFn(callback) === true) { + callback.call(this, cont); + return; + } + } + +}; + + +SampleWidgetType.prototype = { + + create: function(callback) + { + dfx.foreach(items, function(item) { + return true; + }); + + if (dfx.isFn(callback) === true) { + callback.call(this); + } + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + var self = this; + this.createChildren(null, function() { + callback.call(self, div); + return; + }); + } + +}; \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php new file mode 100644 index 000000000..a3c55bf36 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CreateWidgetTypeCallbackUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='CreateWidgetTypeCallbackUnitTest.js') + { + return [ + 18 => 1, + 23 => 2, + 26 => 1, + 30 => 1, + 34 => 1, + 43 => 2, + 91 => 1, + 123 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc new file mode 100644 index 000000000..acf9baf7e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php new file mode 100644 index 000000000..333952f6c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowNewWidgetUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [4 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc new file mode 100644 index 000000000..337914a85 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc @@ -0,0 +1,182 @@ +getMessage()); + }//end try + + if ($something === NULL) { + if ($bar !== NULL) { + } + } + + return $issueid; + +}//end addIssue() + +/** + * Adds a new issue. + * + * Returns the new issue id. + * + * @param string $title Title of the new issue. + * @param string $description The description of the issue. + * @param string $reporter Asset id of the reporter. + * @param integer $projectid Id of the project that the issue belongs to. + * @param array $tags Array of tags. + * @param string $status The status of the issue. + * @param string $assignedTo The asset id of the user that the issue is + * assigned to. + * @param string $reportedDate If set then this date will be used instead of the + * current date and time. + * @param integer $reportedMilestone Reported milestone. + * + * @return integer + * @throws ChannelException If there is an error. + * + */ +public static function addIssue( + $title, + $description, + $reporter=NULL, + $projectid=NULL, + array $tags=array(), + $status=NULL, + $assignedTo=NULL, + $reportedDate=NULL, + $reportedMilestone=NULL +) { + // Get current projectid if not specified. + if ($projectid === NULL) { + Channels::includeSystem('Project'); + $projectid = Project::getCurrentProjectId(); + Channels::modifyBasket('project', $projectid); + } + +}//end addIssue() diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php new file mode 100644 index 000000000..315808bd9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class AjaxNullComparisonUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 41 => 1, + 53 => 1, + 64 => 1, + 77 => 1, + 92 => 1, + 122 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc new file mode 100644 index 000000000..992a7dc19 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php new file mode 100644 index 000000000..423f242d9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EvalObjectFactoryUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + 21 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc new file mode 100644 index 000000000..7999763f2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php new file mode 100644 index 000000000..16e4cfb27 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GetRequestDataUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 8 => 1, + 21 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc new file mode 100644 index 000000000..f9148a782 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc @@ -0,0 +1,9 @@ +myFunction(); +return $obj->variable; +return MyClass::VARIABLE; +return $variable; +return ($var + 1); +?> \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php new file mode 100644 index 000000000..323637868 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ReturnFunctionValueUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js new file mode 100644 index 000000000..46d90cf9f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js @@ -0,0 +1,18 @@ +one = (1 + 2); +two = (one + 2); +two = (one + one); +three = ('1' + 2); + +four = ['1', two].join(); +four = ['1', two].join(''); +four = ['1', [one, two].join(',')].join(' '); +four = ['1', [one, two].join()].join(' '); +four = ['1', [one, two].join()].join(); + +five = 'string' + ['1', [one, two].join()].join() + 'string'; + +six = myArray.join(' '); +six = [arrayOne, arrayTwo].join(); + +// This is fine because the array is not created inline. +var x = 'x' + test[x].join('p') + 't'; \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php new file mode 100644 index 000000000..ecd490a43 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class JoinStringsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='JoinStringsUnitTest.js') + { + if ($testFile !== 'JoinStringsUnitTest.js') { + return []; + } + + return [ + 6 => 1, + 7 => 1, + 8 => 2, + 9 => 2, + 10 => 2, + 12 => 2, + 15 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml new file mode 100644 index 000000000..92407957a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml @@ -0,0 +1,18 @@ + + + The MySource coding standard builds on the Squiz coding standard. Currently used for MySource Mini development. + + */Tests/* + */Oven/* + */data/* + */jquery.js + */jquery.*.js + */viper/* + DALConf.inc + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 000000000..b5d53fdf0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,22 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml new file mode 100644 index 000000000..fe8162000 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml @@ -0,0 +1,177 @@ + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + /** + * The Foo class. + */ + +class Foo +{ +} + ]]> + + + + + The Foo class. + */ +class Foo +{ +} + ]]> + + + The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + * A helper for the Bar class. + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + * + * A helper for the Bar class. + * + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + + + * @see Bar + */ +class Foo +{ +} + ]]> + + + + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + + Release: 1.0 + */ +class Foo +{ +} + ]]> + + + 1.0 + */ +class Foo +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml new file mode 100644 index 000000000..eef0b4e39 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml @@ -0,0 +1,286 @@ + + + + + + + /** + * Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + ]]> + + + + + Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * + * PHP version 5 + * + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + + + @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + @category Foo + * @category Bar + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + @package Foo_Helpers + * @category Foo + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml new file mode 100644 index 000000000..621649f24 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml @@ -0,0 +1,230 @@ + + + + + + + /** + * Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + + + Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + * Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + * Long description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + * + * Long description here. + * + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + * @return void + */ + function foo() + { + } + ]]> + + + + * + * @return void + */ + function foo() + { + } + ]]> + + + + + FooException + */ + function foo() + { + } + ]]> + + + @throws + */ + function foo() + { + } + ]]> + + + + + @return void + */ + function foo() + { + } + ]]> + + + + + + + + $foo Foo parameter + * @param string $bar Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + $qux Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + + + $foo Foo parameter + * @param string $bar Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + $bar Bar parameter + * @param string $foo Foo parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml new file mode 100644 index 000000000..53056e2a9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml @@ -0,0 +1,19 @@ + + + + + + + // A comment. + ]]> + + + # A comment. + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml new file mode 100644 index 000000000..ce430fb12 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml @@ -0,0 +1,36 @@ + + + + + + + ($foo) { +} + ]]> + + + ($foo){ +} + ]]> + + + + + { +} + ]]> + + + { +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml new file mode 100644 index 000000000..96d451dc4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml @@ -0,0 +1,60 @@ + + + + + + + && $bar +) { +} + ]]> + + + && $bar +) { +} + ]]> + + + + + && $bar +) { +} + ]]> + + + && + $bar +) { +} + ]]> + + + + + ) { +} + ]]> + + + ) { +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml new file mode 100644 index 000000000..6d115be76 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml @@ -0,0 +1,24 @@ + + + require_once. Anywhere you are conditionally including a class file (for example, factory methods), use include_once. Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with require_once will not be included again by include_once. + ]]> + + + include_once and require_once are statements, not functions. Parentheses should not surround the subject filename. + ]]> + + + + + + + ('PHP/CodeSniffer.php'); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml new file mode 100644 index 000000000..e4911ef3b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml new file mode 100644 index 000000000..e825c5533 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml @@ -0,0 +1,35 @@ + + + + + + + = $bar; + ]]> + + + = + $bar; + ]]> + + + + + = $bar; + ]]> + + + = $bar; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml new file mode 100644 index 000000000..f87422778 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + ( $bar, $baz, $quux ) ; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml new file mode 100644 index 000000000..ced9ae2e5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml @@ -0,0 +1,41 @@ + + + + + + + () use ($bar) { +}; + ]]> + + + ()use($bar){ +}; + ]]> + + + + + $bar, + $baz +) { +}; + ]]> + + + $bar, +$baz) +{ +}; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml new file mode 100644 index 000000000..56196cb62 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $persistent = false) +{ + ... +} + ]]> + + + $persistent = false, $dsn) +{ + ... +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml new file mode 100644 index 000000000..d16087919 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml new file mode 100644 index 000000000..60841dd4c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml new file mode 100644 index 000000000..4c707bdd1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + publicVar; + protected $protectedVar; + private $_privateVar; +} + ]]> + + + _publicVar; + protected $_protectedVar; + private $privateVar; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml new file mode 100644 index 000000000..9dee905db --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml @@ -0,0 +1,39 @@ + + + + + + + ->bar() + ->baz(); + ]]> + + + -> + bar()-> + baz(); + ]]> + + + + + ->bar() + ->baz(); + ]]> + + + ->bar() +->baz(); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml new file mode 100644 index 000000000..c8d6e2748 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + } + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml new file mode 100644 index 000000000..fafa07ace --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml @@ -0,0 +1,29 @@ + + + + + + + if ($test) { + $var = 1; + } +} + ]]> + + + if ($test) { +$var = 1; +} +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..dbd61f3d2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,150 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $errorData = [strtolower($tokens[$stackPtr]['content'])]; + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData); + return; + } + + $curlyBrace = $tokens[$stackPtr]['scope_opener']; + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBrace - 1), $stackPtr, true); + $classLine = $tokens[$lastContent]['line']; + $braceLine = $tokens[$curlyBrace]['line']; + if ($braceLine === $classLine) { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'same line'); + $error = 'Opening brace of a %s must be on the line after the definition'; + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceNewLine', $errorData); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($curlyBrace - 1), ''); + } + + $phpcsFile->fixer->addNewlineBefore($curlyBrace); + $phpcsFile->fixer->endChangeset(); + } + + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'new line'); + + if ($braceLine > ($classLine + 1)) { + $error = 'Opening brace of a %s must be on the line following the %s declaration; found %s line(s)'; + $data = [ + $tokens[$stackPtr]['content'], + $tokens[$stackPtr]['content'], + ($braceLine - $classLine - 1), + ]; + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceWrongLine', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($curlyBrace - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] === ($tokens[$curlyBrace]['line'] + 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + }//end if + + if ($tokens[($curlyBrace + 1)]['content'] !== $phpcsFile->eolChar) { + $error = 'Opening %s brace must be on a line by itself'; + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($curlyBrace + 1), null, true); + if ($tokens[$nextNonWhitespace]['code'] === T_PHPCS_IGNORE) { + // Don't auto-fix if the next thing is a PHPCS ignore annotation. + $phpcsFile->addError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData); + } else { + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData); + if ($fix === true) { + $phpcsFile->fixer->addNewline($curlyBrace); + } + } + } + + if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($curlyBrace - 1)]['content']; + if ($prevContent === $phpcsFile->eolChar) { + $spaces = 0; + } else { + $spaces = $tokens[($curlyBrace - 1)]['length']; + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $expected = ($tokens[$first]['column'] - 1); + if ($spaces !== $expected) { + $error = 'Expected %s spaces before opening brace; %s found'; + $data = [ + $expected, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expected); + if ($spaces === 0) { + $phpcsFile->fixer->addContentBefore($curlyBrace, $indent); + } else { + $phpcsFile->fixer->replaceToken(($curlyBrace - 1), $indent); + } + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 000000000..a01ea2cc7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,119 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class ClassCommentSniff extends FileCommentSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $type = strtolower($tokens[$stackPtr]['content']); + $errorData = [$type]; + + $find = Tokens::$methodPrefixes; + $find[T_WHITESPACE] = T_WHITESPACE; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $errorData[] = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError('Missing doc comment for %s %s', $stackPtr, 'Missing', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes'); + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a %s comment', $stackPtr, 'WrongStyle', $errorData); + return; + } + + // Check each tag. + $this->processTags($phpcsFile, $stackPtr, $tokens[$commentEnd]['comment_opener']); + + }//end process() + + + /** + * Process the version tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processVersion($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if ((strstr($content, 'Release:') === false)) { + $error = 'Invalid version "%s" in doc comment; consider "Release: " instead'; + $data = [$content]; + $phpcsFile->addWarning($error, $tag, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 000000000..6a4458468 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,582 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class FileCommentSniff implements Sniff +{ + + /** + * Tags in correct order and related info. + * + * @var array + */ + protected $tags = [ + '@category' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@package' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@subpackage' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@author' => [ + 'required' => true, + 'allow_multiple' => true, + ], + '@copyright' => [ + 'required' => false, + 'allow_multiple' => true, + ], + '@license' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@version' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@link' => [ + 'required' => true, + 'allow_multiple' => true, + ], + '@see' => [ + 'required' => false, + 'allow_multiple' => true, + ], + '@since' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@deprecated' => [ + 'required' => false, + 'allow_multiple' => false, + ], + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the next non whitespace token. + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + // Allow declare() statements at the top of the file. + if ($tokens[$commentStart]['code'] === T_DECLARE) { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($commentStart + 1)); + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), null, true); + } + + // Ignore vim header. + if ($tokens[$commentStart]['code'] === T_COMMENT) { + if (strstr($tokens[$commentStart]['content'], 'vim:') !== false) { + $commentStart = $phpcsFile->findNext( + T_WHITESPACE, + ($commentStart + 1), + null, + true + ); + } + } + + $errorToken = ($stackPtr + 1); + if (isset($tokens[$errorToken]) === false) { + $errorToken--; + } + + if ($tokens[$commentStart]['code'] === T_CLOSE_TAG) { + // We are only interested if this is the first open tag. + return ($phpcsFile->numTokens + 1); + } else if ($tokens[$commentStart]['code'] === T_COMMENT) { + $error = 'You must use "/**" style comments for a file comment'; + $phpcsFile->addError($error, $errorToken, 'WrongStyle'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + return ($phpcsFile->numTokens + 1); + } else if ($commentStart === false + || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG + ) { + $phpcsFile->addError('Missing file doc comment', $errorToken, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + for ($nextToken = ($commentEnd + 1); $nextToken < $phpcsFile->numTokens; $nextToken++) { + if ($tokens[$nextToken]['code'] === T_WHITESPACE) { + continue; + } + + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE + && isset($tokens[$nextToken]['attribute_closer']) === true + ) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } + + if ($nextToken === $phpcsFile->numTokens) { + $nextToken--; + } + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + + // Check the PHP Version, which should be in some text before the first tag. + $found = false; + for ($i = ($commentStart + 1); $i < $commentEnd; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG) { + break; + } else if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING + && strstr(strtolower($tokens[$i]['content']), 'php version') !== false + ) { + $found = true; + break; + } + } + + if ($found === false) { + $error = 'PHP version not specified'; + $phpcsFile->addWarning($error, $commentEnd, 'MissingVersion'); + } + + // Check each tag. + $this->processTags($phpcsFile, $stackPtr, $commentStart); + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + + /** + * Processes each required or optional tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart Position in the stack where the comment started. + * + * @return void + */ + protected function processTags($phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if (get_class($this) === 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff') { + $docBlock = 'file'; + } else { + $docBlock = 'class'; + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + $foundTags = []; + $tagTokens = []; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $name = $tokens[$tag]['content']; + if (isset($this->tags[$name]) === false) { + continue; + } + + if ($this->tags[$name]['allow_multiple'] === false && isset($tagTokens[$name]) === true) { + $error = 'Only one %s tag is allowed in a %s comment'; + $data = [ + $name, + $docBlock, + ]; + $phpcsFile->addError($error, $tag, 'Duplicate'.ucfirst(substr($name, 1)).'Tag', $data); + } + + $foundTags[] = $name; + $tagTokens[$name][] = $tag; + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in %s comment'; + $data = [ + $name, + $docBlock, + ]; + $phpcsFile->addError($error, $tag, 'Empty'.ucfirst(substr($name, 1)).'Tag', $data); + continue; + } + }//end foreach + + // Check if the tags are in the correct position. + $pos = 0; + foreach ($this->tags as $tag => $tagData) { + if (isset($tagTokens[$tag]) === false) { + if ($tagData['required'] === true) { + $error = 'Missing %s tag in %s comment'; + $data = [ + $tag, + $docBlock, + ]; + $phpcsFile->addError($error, $commentEnd, 'Missing'.ucfirst(substr($tag, 1)).'Tag', $data); + } + + continue; + } else { + $method = 'process'.substr($tag, 1); + if (method_exists($this, $method) === true) { + // Process each tag if a method is defined. + call_user_func([$this, $method], $phpcsFile, $tagTokens[$tag]); + } + } + + if (isset($foundTags[$pos]) === false) { + break; + } + + if ($foundTags[$pos] !== $tag) { + $error = 'The tag in position %s should be the %s tag'; + $data = [ + ($pos + 1), + $tag, + ]; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)).'TagOrder', $data); + } + + // Account for multiple tags. + $pos++; + while (isset($foundTags[$pos]) === true && $foundTags[$pos] === $tag) { + $pos++; + } + }//end foreach + + }//end processTags() + + + /** + * Process the category tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processCategory($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) !== true) { + $newContent = str_replace(' ', '_', $content); + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = ucfirst($firstBit).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= ucfirst($bit).'_'; + } + } + + $error = 'Category name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidCategory', $data); + } + }//end foreach + + }//end processCategory() + + + /** + * Process the package tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processPackage($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) === true) { + continue; + } + + $newContent = str_replace(' ', '_', $content); + $newContent = trim($newContent, '_'); + $newContent = preg_replace('/[^A-Za-z_]/', '', $newContent); + + if ($newContent === '') { + $error = 'Package name "%s" is not valid'; + $data = [$content]; + $phpcsFile->addError($error, $tag, 'InvalidPackageValue', $data); + } else { + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $error = 'Package name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidPackage', $data); + }//end if + }//end foreach + + }//end processPackage() + + + /** + * Process the subpackage tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processSubpackage($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) === true) { + continue; + } + + $newContent = str_replace(' ', '_', $content); + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $error = 'Subpackage name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidSubpackage', $data); + }//end foreach + + }//end processSubpackage() + + + /** + * Process the author tag(s) that this header comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processAuthor($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $local = '\da-zA-Z-_+'; + // Dot character cannot be the first or last character in the local-part. + $localMiddle = $local.'.\w'; + if (preg_match('/^([^<]*)\s+<(['.$local.'](['.$localMiddle.']*['.$local.'])*@[\da-zA-Z][-.\w]*[\da-zA-Z]\.[a-zA-Z]{2,})>$/', $content) === 0) { + $error = 'Content of the @author tag must be in the form "Display Name "'; + $phpcsFile->addError($error, $tag, 'InvalidAuthors'); + } + } + + }//end processAuthor() + + + /** + * Process the copyright tags. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processCopyright($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $matches = []; + if (preg_match('/^([0-9]{4})((.{1})([0-9]{4}))? (.+)$/', $content, $matches) !== 0) { + // Check earliest-latest year order. + if ($matches[3] !== '' && $matches[3] !== null) { + if ($matches[3] !== '-') { + $error = 'A hyphen must be used between the earliest and latest year'; + $phpcsFile->addError($error, $tag, 'CopyrightHyphen'); + } + + if ($matches[4] !== '' && $matches[4] !== null && $matches[4] < $matches[1]) { + $error = "Invalid year span \"$matches[1]$matches[3]$matches[4]\" found; consider \"$matches[4]-$matches[1]\" instead"; + $phpcsFile->addWarning($error, $tag, 'InvalidCopyright'); + } + } + } else { + $error = '@copyright tag must contain a year and the name of the copyright holder'; + $phpcsFile->addError($error, $tag, 'IncompleteCopyright'); + } + }//end foreach + + }//end processCopyright() + + + /** + * Process the license tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processLicense($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $matches = []; + preg_match('/^([^\s]+)\s+(.*)/', $content, $matches); + if (count($matches) !== 3) { + $error = '@license tag must contain a URL and a license name'; + $phpcsFile->addError($error, $tag, 'IncompleteLicense'); + } + } + + }//end processLicense() + + + /** + * Process the version tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processVersion($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (strstr($content, 'CVS:') === false + && strstr($content, 'SVN:') === false + && strstr($content, 'GIT:') === false + && strstr($content, 'HG:') === false + ) { + $error = 'Invalid version "%s" in file comment; consider "CVS: " or "SVN: " or "GIT: " or "HG: " instead'; + $data = [$content]; + $phpcsFile->addWarning($error, $tag, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 000000000..408856fc5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,525 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCommentSniff implements Sniff +{ + + /** + * Disable the check for functions with a lower visibility than the value given. + * + * Allowed values are public, protected, and private. + * + * @var string + */ + public $minimumVisibility = 'private'; + + /** + * Array of methods which do not require a return type. + * + * @var array + */ + public $specialMethods = [ + '__construct', + '__destruct', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $scopeModifier = $phpcsFile->getMethodProperties($stackPtr)['scope']; + if ($scopeModifier === 'protected' + && $this->minimumVisibility === 'public' + || $scopeModifier === 'private' + && ($this->minimumVisibility === 'public' || $this->minimumVisibility === 'protected') + ) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $ignore = Tokens::$methodPrefixes; + $ignore[T_WHITESPACE] = T_WHITESPACE; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + // Inline comments might just be closing comments for + // control structures or functions instead of function comments + // using the wrong comment type. If there is other code on the line, + // assume they relate to that code. + $prev = $phpcsFile->findPrevious($ignore, ($commentEnd - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $commentEnd = $prev; + } + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $function = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError( + 'Missing doc comment for function %s()', + $stackPtr, + 'Missing', + [$function] + ); + $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no'); + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes'); + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle'); + return; + } + + if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + for ($i = ($commentEnd + 1); $i < $stackPtr; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'There must be no blank lines after the function comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfter'); + break; + } + } + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } + } + + $this->processReturn($phpcsFile, $stackPtr, $commentStart); + $this->processThrows($phpcsFile, $stackPtr, $commentStart); + $this->processParams($phpcsFile, $stackPtr, $commentStart); + + }//end process() + + + /** + * Process the return comment of this function comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = in_array($methodName, $this->specialMethods, true); + + $return = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } + } else { + if ($isSpecialMethod === true) { + return; + } + + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + } + + if ($exception === null) { + $error = 'Exception type missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentEnd = 0; + $commentTokens = []; + + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/((?:(?![$.]|&(?=\$)).)*)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + if (empty($matches) === false) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + $commentEnd = $i; + $commentTokens[] = $i; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + }//end if + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'comment_end' => $commentEnd, + 'comment_tokens' => $commentTokens, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so add + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + if (trim($param['type']) !== '') { + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + 1); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix === true) { + $commentToken = ($param['tag'] + 2); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + + $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']); + + $padding = str_repeat(' ', ($tokens[$star]['column'] - 1)); + $padding .= '* '; + $padding .= str_repeat(' ', $spaceLength); + + $content .= wordwrap( + $param['comment'], + $wrapLength, + $phpcsFile->eolChar.$padding + ); + + $phpcsFile->fixer->replaceToken($commentToken, $content); + for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + }//end if + }//end if + }//end if + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = [ + $param['var'], + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } else if (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the param name. + $spaces = ($maxVar - strlen($param['var']) + 1); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix === true) { + $commentToken = ($param['tag'] + 2); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + + $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']); + + $padding = str_repeat(' ', ($tokens[$star]['column'] - 1)); + $padding .= '* '; + $padding .= str_repeat(' ', $spaceLength); + + $content .= wordwrap( + $param['comment'], + $wrapLength, + $phpcsFile->eolChar.$padding + ); + + $phpcsFile->fixer->replaceToken($commentToken, $content); + for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + }//end if + }//end if + + // Check the alignment of multi-line param comments. + if ($param['tag'] !== $param['comment_end']) { + $wrapLength = ($tokens[($param['tag'] + 2)]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $startColumn = ($tokens[($param['tag'] + 2)]['column'] + $tokens[($param['tag'] + 2)]['length'] - $wrapLength); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $expected = ($startColumn - $tokens[$star]['column'] - 1); + + foreach ($param['comment_tokens'] as $commentToken) { + if ($tokens[$commentToken]['column'] === $startColumn) { + continue; + } + + $found = 0; + if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $found = $tokens[($commentToken - 1)]['length']; + } + + $error = 'Parameter comment not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + if ($found < $expected) { + $code = 'ParamCommentAlignment'; + } else { + $code = 'ParamCommentAlignmentExceeded'; + } + + $fix = $phpcsFile->addFixableError($error, $commentToken, $code, $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($commentToken - 1), $padding); + } else { + $phpcsFile->fixer->addContentBefore($commentToken, $padding); + } + } + }//end foreach + }//end if + }//end foreach + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php new file mode 100644 index 000000000..aa9f37537 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'][0] === '#') { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '# ...'); + + $error = 'Perl-style comments are not allowed. Use "// Comment."'; + $error .= ' or "/* comment */" instead.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle'); + if ($fix === true) { + $newComment = ltrim($tokens[$stackPtr]['content'], '# '); + $newComment = '// '.$newComment; + $phpcsFile->fixer->replaceToken($stackPtr, $newComment); + } + } else if ($tokens[$stackPtr]['content'][0] === '/' + && $tokens[$stackPtr]['content'][1] === '/' + ) { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '// ...'); + } else if ($tokens[$stackPtr]['content'][0] === '/' + && $tokens[$stackPtr]['content'][1] === '*' + ) { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '/* ... */'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100644 index 000000000..edd2d6beb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Sniffs\AbstractPatternSniff; + +class ControlSignatureSniff extends AbstractPatternSniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = true; + + + /** + * Returns the patterns that this test wishes to verify. + * + * @return string[] + */ + protected function getPatterns() + { + return [ + 'do {EOL...} while (...);EOL', + 'while (...) {EOL', + 'for (...) {EOL', + 'if (...) {EOL', + 'foreach (...) {EOL', + '} else if (...) {EOL', + '} elseif (...) {EOL', + '} else {EOL', + 'do {EOL', + 'match (...) {EOL', + ]; + + }//end getPatterns() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php new file mode 100644 index 000000000..fff62bb1e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php @@ -0,0 +1,283 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultiLineConditionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + $spaceAfterOpen = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($openBracket + 1)]['content'], $phpcsFile->eolChar) !== false) { + $spaceAfterOpen = 'newline'; + } else { + $spaceAfterOpen = $tokens[($openBracket + 1)]['length']; + } + } + + if ($spaceAfterOpen !== 0) { + $error = 'First condition of a multi-line IF statement must directly follow the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, ($openBracket + 1), 'SpacingAfterOpenBrace'); + if ($fix === true) { + if ($spaceAfterOpen === 'newline') { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + } + + // We need to work out how far indented the if statement + // itself is, so we can work out how far to indent conditions. + $statementIndent = 0; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + $i++; + break; + } + } + + if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) { + $statementIndent = $tokens[$i]['length']; + } + + // Each line between the parenthesis should be indented 4 spaces + // and start with an operator, unless the line is inside a + // function call, in which case it is ignored. + $prevLine = $tokens[$openBracket]['line']; + for ($i = ($openBracket + 1); $i <= $closeBracket; $i++) { + if ($i === $closeBracket && $tokens[$openBracket]['line'] !== $tokens[$i]['line']) { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + // Closing bracket is on the same line as a condition. + $error = 'Closing parenthesis of a multi-line IF statement must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketNewLine'); + if ($fix === true) { + // Account for a comment at the end of the line. + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] !== T_COMMENT + && isset(Tokens::$phpcsCommentTokens[$tokens[$next]['code']]) === false + ) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } else { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($closeBracket, ''); + $phpcsFile->fixer->addContentBefore($next, ')'); + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + + if ($tokens[$i]['line'] !== $prevLine) { + if ($tokens[$i]['line'] === $tokens[$closeBracket]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, $i, null, true); + if ($next !== $closeBracket) { + $expectedIndent = ($statementIndent + $this->indent); + } else { + // Closing brace needs to be indented to the same level + // as the statement. + $expectedIndent = $statementIndent; + }//end if + } else { + $expectedIndent = ($statementIndent + $this->indent); + }//end if + + if ($tokens[$i]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true + ) { + $prevLine = $tokens[$i]['line']; + continue; + } + + // We changed lines, so this should be a whitespace indent token. + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundIndent = 0; + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($expectedIndent !== $foundIndent) { + $error = 'Multi-line IF statement not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Alignment', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $spaces); + } else { + $phpcsFile->fixer->replaceToken($i, $spaces); + } + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i, null, true); + if ($next !== $closeBracket && $tokens[$next]['line'] === $tokens[$i]['line']) { + if (isset(Tokens::$booleanOperators[$tokens[$next]['code']]) === false) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $openBracket, true); + $fixable = true; + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === false + && $phpcsFile->findNext(T_WHITESPACE, ($prev + 1), $next, true) !== false + ) { + // Condition spread over multi-lines interspersed with comments. + $fixable = false; + } + + $error = 'Each line in a multi-line IF statement must begin with a boolean operator'; + if ($fixable === false) { + $phpcsFile->addError($error, $next, 'StartWithBoolean'); + } else { + $fix = $phpcsFile->addFixableError($error, $next, 'StartWithBoolean'); + if ($fix === true) { + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->addContentBefore($next, $tokens[$prev]['content'].' '); + $phpcsFile->fixer->endChangeset(); + } else { + for ($x = ($prev + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + } + } + } + }//end if + }//end if + + $prevLine = $tokens[$i]['line']; + }//end if + + if ($tokens[$i]['code'] === T_STRING) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + // This is a function call, so skip to the end as they + // have their own indentation rules. + $i = $tokens[$next]['parenthesis_closer']; + $prevLine = $tokens[$i]['line']; + continue; + } + } + }//end for + + // From here on, we are checking the spacing of the opening and closing + // braces. If this IF statement does not use braces, we end here. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // The opening brace needs to be one space away from the closing parenthesis. + $openBrace = $tokens[$stackPtr]['scope_opener']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), $openBrace, true); + if ($next !== false) { + // Probably comments in between tokens, so don't check. + return; + } + + if ($tokens[$openBrace]['line'] > $tokens[$closeBracket]['line']) { + $length = -1; + } else if ($openBrace === ($closeBracket + 1)) { + $length = 0; + } else if ($openBrace === ($closeBracket + 2) + && $tokens[($closeBracket + 1)]['code'] === T_WHITESPACE + ) { + $length = $tokens[($closeBracket + 1)]['length']; + } else { + // Confused, so don't check. + $length = 1; + } + + if ($length === 1) { + return; + } + + $data = [$length]; + $code = 'SpaceBeforeOpenBrace'; + + $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement; found '; + if ($length === -1) { + $error .= 'newline'; + $code = 'NewlineBeforeOpenBrace'; + } else { + $error .= '%s spaces'; + } + + $fix = $phpcsFile->addFixableError($error, ($closeBracket + 1), $code, $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContent($closeBracket, ' '); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket + 1), ' '); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php new file mode 100644 index 000000000..04f208dee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php @@ -0,0 +1,136 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IncludingFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_INCLUDE_ONCE, + T_REQUIRE_ONCE, + T_REQUIRE, + T_INCLUDE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS) { + $error = '"%s" is a statement not a function; no parentheses are required'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BracketsNotRequired', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($tokens[$nextToken]['parenthesis_closer'], ''); + if ($tokens[($nextToken - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($nextToken, ' '); + } else { + $phpcsFile->fixer->replaceToken($nextToken, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if (count($tokens[$stackPtr]['conditions']) !== 0) { + $inCondition = true; + } else { + $inCondition = false; + } + + // Check to see if this including statement is within the parenthesis + // of a condition. If that's the case then we need to process it as being + // within a condition, as they are checking the return value. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $left => $right) { + if (isset($tokens[$left]['parenthesis_owner']) === true) { + $inCondition = true; + } + } + } + + // Check to see if they are assigning the return value of this + // including call. If they are then they are probably checking it, so + // it's conditional. + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset(Tokens::$assignmentTokens[$tokens[$previous]['code']]) === true) { + // The have assigned the return value to it, so its conditional. + $inCondition = true; + } + + $tokenCode = $tokens[$stackPtr]['code']; + if ($inCondition === true) { + // We are inside a conditional statement. We need an include_once. + if ($tokenCode === T_REQUIRE_ONCE) { + $error = 'File is being conditionally included; '; + $error .= 'use "include_once" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseIncludeOnce'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'include_once'); + } + } else if ($tokenCode === T_REQUIRE) { + $error = 'File is being conditionally included; '; + $error .= 'use "include" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseInclude'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'include'); + } + } + } else { + // We are unconditionally including, we need a require_once. + if ($tokenCode === T_INCLUDE_ONCE) { + $error = 'File is being unconditionally included; '; + $error .= 'use "require_once" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseRequireOnce'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'require_once'); + } + } else if ($tokenCode === T_INCLUDE) { + $error = 'File is being unconditionally included; '; + $error .= 'use "require" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseRequire'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'require'); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php new file mode 100644 index 000000000..0a7ff7db1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php @@ -0,0 +1,106 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class MultiLineAssignmentSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Equal sign can't be the last thing on the line. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + // Bad assignment. + return; + } + + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Multi-line assignments must have the equal sign on the second line'; + $phpcsFile->addError($error, $stackPtr, 'EqualSignLine'); + return; + } + + // Make sure it is the first thing on the line, otherwise we ignore it. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), false, true); + if ($prev === false) { + // Bad assignment. + return; + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + return; + } + + // Find the required indent based on the ident of the previous line. + $assignmentIndent = 0; + $prevLine = $tokens[$prev]['line']; + for ($i = ($prev - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $prevLine) { + $i++; + break; + } + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + $assignmentIndent = $tokens[$i]['length']; + } + + // Find the actual indent. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1)); + + $expectedIndent = ($assignmentIndent + $this->indent); + $foundIndent = $tokens[$prev]['length']; + if ($foundIndent !== $expectedIndent) { + $error = 'Multi-line assignment not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $phpcsFile->addError($error, $stackPtr, 'Indent', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php new file mode 100644 index 000000000..3a339abe4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php @@ -0,0 +1,628 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallSignatureSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * If TRUE, multiple arguments can be defined per line in a multi-line call. + * + * @var boolean + */ + public $allowMultipleArguments = true; + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$functionNameTokens; + + $tokens[] = T_VARIABLE; + $tokens[] = T_CLOSE_CURLY_BRACKET; + $tokens[] = T_CLOSE_SQUARE_BRACKET; + $tokens[] = T_CLOSE_PARENTHESIS; + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$stackPtr]['scope_condition']) === true + ) { + // Not a function call. + return; + } + + // Find the next non-empty token. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + // Not a function call. + return; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true); + if ($tokens[$previous]['code'] === T_FUNCTION) { + // It's a function definition, not a function call. + return; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + if (($stackPtr + 1) !== $openBracket) { + // Checking this: $value = my_function[*](...). + $error = 'Space before opening parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $openBracket; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Modify the bracket as well to ensure a conflict if the bracket + // has been changed in some way by another sniff. + $phpcsFile->fixer->replaceToken($openBracket, '('); + $phpcsFile->fixer->endChangeset(); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + if (isset(Tokens::$emptyTokens[$tokens[($closeBracket + 1)]['code']]) === true) { + $error = 'Space after closing parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpaceAfterCloseBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closeBracket + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Modify the bracket as well to ensure a conflict if the bracket + // has been changed in some way by another sniff. + $phpcsFile->fixer->replaceToken($closeBracket, ')'); + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Check if this is a single line or multi-line function call. + if ($this->isMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens); + } else { + $this->processSingleLineCall($phpcsFile, $stackPtr, $openBracket, $tokens); + } + + }//end process() + + + /** + * Determine if this is a multi-line function call. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + return true; + } + + return false; + + }//end isMultiLineCall() + + + /** + * Processes single-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closer = $tokens[$openBracket]['parenthesis_closer']; + if ($openBracket === ($closer - 1)) { + return; + } + + // If the function call has no arguments or comments, enforce 0 spaces. + $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closer, true); + if ($next === false) { + $requiredSpacesAfterOpen = 0; + $requiredSpacesBeforeClose = 0; + } else { + $requiredSpacesAfterOpen = $this->requiredSpacesAfterOpen; + $requiredSpacesBeforeClose = $this->requiredSpacesBeforeClose; + } + + if ($requiredSpacesAfterOpen === 0 && $tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + // Checking this: $value = my_function([*]...). + $error = 'Space after opening parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } else if ($requiredSpacesAfterOpen > 0) { + $spaceAfterOpen = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening parenthesis; %s found'; + $data = [ + $requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), $padding); + } + } + } + }//end if + + // Checking this: $value = my_function(...[*]). + $spaceBeforeClose = 0; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), $openBracket, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Need a newline after these tokens, so ignore this rule. + return; + } + + if ($tokens[$prev]['line'] !== $tokens[$closer]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closer - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closer - 1)]['length']; + } + + if ($spaceBeforeClose !== $requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing parenthesis; %s found'; + $data = [ + $requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeCloseBracket', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredSpacesBeforeClose); + + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closer, $padding); + } else if ($spaceBeforeClose === 'newline') { + $phpcsFile->fixer->beginChangeset(); + + $closingContent = ')'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $closingContent .= ';'; + for ($i = ($closer + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // We want to jump over any whitespace or inline comment and + // move the closing parenthesis after any other token. + $prev = ($closer - 1); + while (isset(Tokens::$emptyTokens[$tokens[$prev]['code']]) === true) { + if (($tokens[$prev]['code'] === T_COMMENT) + && (strpos($tokens[$prev]['content'], '*/') !== false) + ) { + break; + } + + $prev--; + } + + $phpcsFile->fixer->addContent($prev, $padding.$closingContent); + + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), null, true); + for ($i = ($prevNonWhitespace + 1); $i <= $closer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($closer - 1), $padding); + }//end if + }//end if + }//end if + + }//end processSingleLineCall() + + + /** + * Processes multi-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + // We need to work out how far indented the function + // call itself is, so we can work out how far to + // indent the arguments. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + if ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($first - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING + ) { + // We are in a multi-line string, so find the start and use + // the indent from there. + $prev = $phpcsFile->findPrevious(T_CONSTANT_ENCAPSED_STRING, ($first - 2), null, true); + $first = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $prev, true); + if ($first === false) { + $first = ($prev + 1); + } + } + + $foundFunctionIndent = 0; + if ($first !== false) { + if ($tokens[$first]['code'] === T_INLINE_HTML + || ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($first - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING) + ) { + $trimmed = ltrim($tokens[$first]['content']); + if ($trimmed === '') { + $foundFunctionIndent = strlen($tokens[$first]['content']); + } else { + $foundFunctionIndent = (strlen($tokens[$first]['content']) - strlen($trimmed)); + } + } else { + $foundFunctionIndent = ($tokens[$first]['column'] - 1); + } + } + + // Make sure the function indent is divisible by the indent size. + // We round down here because this accounts for times when the + // surrounding code is indented a little too far in, and not correctly + // at a tab stop. Without this, the function will be indented a further + // $indent spaces to the right. + $functionIndent = (int) (floor($foundFunctionIndent / $this->indent) * $this->indent); + $adjustment = 0; + + if ($foundFunctionIndent !== $functionIndent) { + $error = 'Opening statement of multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $functionIndent, + $foundFunctionIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'OpeningIndent', $data); + if ($fix === true) { + $adjustment = ($functionIndent - $foundFunctionIndent); + $padding = str_repeat(' ', $functionIndent); + if ($foundFunctionIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $error = 'Opening parenthesis of a multi-line function call must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->addContent( + $openBracket, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + } + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) { + $error = 'Closing parenthesis of a multi-line function call must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore( + $closeBracket, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + } + } + + // Each line between the parenthesis should be indented n spaces. + $lastLine = ($tokens[$openBracket]['line'] - 1); + $argStart = null; + $argEnd = null; + + // Start processing at the first argument. + $i = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + + if ($tokens[$i]['line'] > ($tokens[$openBracket]['line'] + 1)) { + $error = 'The first argument in a multi-line function call must be on the line after the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, $i, 'FirstArgumentPosition'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($openBracket + 1); $x < $i; $x++) { + if ($tokens[$x]['line'] === $tokens[$openBracket]['line']) { + continue; + } + + if ($tokens[$x]['line'] === $tokens[$i]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $i = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + + if ($tokens[($i - 1)]['code'] === T_WHITESPACE + && $tokens[($i - 1)]['line'] === $tokens[$i]['line'] + ) { + // Make sure we check the indent. + $i--; + } + + for ($i; $i < $closeBracket; $i++) { + if ($i > $argStart && $i < $argEnd) { + $inArg = true; + } else { + $inArg = false; + } + + if ($tokens[$i]['line'] !== $lastLine) { + $lastLine = $tokens[$i]['line']; + + // Ignore heredoc indentation. + if (isset(Tokens::$heredocTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore multi-line string indentation. + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true + && $tokens[$i]['code'] === $tokens[($i - 1)]['code'] + ) { + continue; + } + + // Ignore inline HTML. + if ($tokens[$i]['code'] === T_INLINE_HTML) { + continue; + } + + if ($tokens[$i]['line'] !== $tokens[$openBracket]['line']) { + // We changed lines, so this should be a whitespace indent token, but first make + // sure it isn't a blank line because we don't need to check indent unless there + // is actually some code to indent. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closeBracket + 1), true); + if ($tokens[$nextCode]['line'] !== $lastLine) { + if ($inArg === false) { + $error = 'Empty lines are not allowed in multi-line function calls'; + $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + continue; + } + } else { + $nextCode = $i; + } + + if ($tokens[$nextCode]['line'] === $tokens[$closeBracket]['line']) { + // Closing brace needs to be indented to the same level + // as the function call. + $inArg = false; + $expectedIndent = ($foundFunctionIndent + $adjustment); + } else { + $expectedIndent = ($foundFunctionIndent + $this->indent + $adjustment); + } + + if ($tokens[$i]['code'] !== T_WHITESPACE + && $tokens[$i]['code'] !== T_DOC_COMMENT_WHITESPACE + ) { + // Just check if it is a multi-line block comment. If so, we can + // calculate the indent from the whitespace before the content. + if ($tokens[$i]['code'] === T_COMMENT + && $tokens[($i - 1)]['code'] === T_COMMENT + ) { + $trimmedLength = strlen(ltrim($tokens[$i]['content'])); + if ($trimmedLength === 0) { + // This is a blank comment line, so indenting it is + // pointless. + continue; + } + + $foundIndent = (strlen($tokens[$i]['content']) - $trimmedLength); + } else { + $foundIndent = 0; + } + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($foundIndent < $expectedIndent + || ($inArg === false + && $expectedIndent !== $foundIndent) + ) { + $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $padding); + if (isset($tokens[$i]['scope_opener']) === true) { + $phpcsFile->fixer->changeCodeBlockIndent($i, $tokens[$i]['scope_closer'], $expectedIndent); + } + } else { + if ($tokens[$i]['code'] === T_COMMENT) { + $comment = $padding.ltrim($tokens[$i]['content']); + $phpcsFile->fixer->replaceToken($i, $comment); + } else { + $phpcsFile->fixer->replaceToken($i, $padding); + } + + if (isset($tokens[($i + 1)]['scope_opener']) === true) { + $phpcsFile->fixer->changeCodeBlockIndent(($i + 1), $tokens[($i + 1)]['scope_closer'], ($expectedIndent - $foundIndent)); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + } else { + $nextCode = $i; + }//end if + + if ($inArg === false) { + $argStart = $nextCode; + $argEnd = $phpcsFile->findEndOfStatement($nextCode, [T_COLON]); + } + }//end if + + // If we are within an argument we should be ignoring commas + // as these are not signalling the end of an argument. + if ($inArg === false && $tokens[$i]['code'] === T_COMMA) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closeBracket, true); + if ($next === false) { + continue; + } + + if ($this->allowMultipleArguments === false) { + // Comma has to be the last token on the line. + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + $error = 'Only one argument is allowed per line in a multi-line function call'; + $fix = $phpcsFile->addFixableError($error, $next, 'MultipleArguments'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($next - 1); $x > $i; $x--) { + if ($tokens[$x]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore( + $next, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + $argStart = $next; + $argEnd = $phpcsFile->findEndOfStatement($next, [T_COLON]); + }//end if + }//end for + + }//end processMultiLineCall() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php new file mode 100644 index 000000000..bd59a7cd9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php @@ -0,0 +1,522 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\OpeningFunctionBraceBsdAllmanSniff; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\OpeningFunctionBraceKernighanRitchieSniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionDeclarationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + if (strtolower($tokens[$stackPtr]['content']) === 'function') { + // Must be one space after the FUNCTION keyword. + if ($tokens[($stackPtr + 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($stackPtr + 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 1) { + $error = 'Expected 1 space after FUNCTION keyword; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterFunction', $data); + if ($fix === true) { + if ($spaces === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + }//end if + + // Must be no space before the opening parenthesis. For closures, this is + // enforced by the previous check because there is no content between the keywords + // and the opening parenthesis. + // Unfinished closures are tokenized as T_FUNCTION however, and can be excluded + // by checking for the scope_opener. + if ($tokens[$stackPtr]['code'] === T_FUNCTION + && (isset($tokens[$stackPtr]['scope_opener']) === true || $phpcsFile->getMethodProperties($stackPtr)['has_body'] === false) + ) { + if ($tokens[($openBracket - 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($openBracket - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($openBracket - 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 0) { + $error = 'Expected 0 spaces before opening parenthesis; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpaceBeforeOpenParen', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket - 1), ''); + } + } + + // Must be no space before semicolon in abstract/interface methods. + if ($phpcsFile->getMethodProperties($stackPtr)['has_body'] === false) { + $end = $phpcsFile->findNext(T_SEMICOLON, $closeBracket); + if ($tokens[($end - 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($end - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($end - 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 0) { + $error = 'Expected 0 spaces before semicolon; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $end, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($end - 1), ''); + } + } + } + }//end if + + // Must be one space before and after USE keyword for closures. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + if ($tokens[($use + 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($use + 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($use + 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space after USE keyword; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $use, 'SpaceAfterUse', $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContent($use, ' '); + } else { + $phpcsFile->fixer->replaceToken(($use + 1), ' '); + } + } + } + + if ($tokens[($use - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($use - 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($use - 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space before USE keyword; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $use, 'SpaceBeforeUse', $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContentBefore($use, ' '); + } else { + $phpcsFile->fixer->replaceToken(($use - 1), ' '); + } + } + } + }//end if + }//end if + + if ($this->isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens); + } else { + $this->processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens); + } + + }//end process() + + + /** + * Determine if this is a multi-line function declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + return true; + } + + // Closures may use the USE keyword and so be multi-line in this way. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + // If the opening and closing parenthesis of the use statement + // are also on the same line, this is a single line declaration. + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $close = $tokens[$open]['parenthesis_closer']; + if ($tokens[$open]['line'] !== $tokens[$close]['line']) { + return true; + } + } + } + + return false; + + }//end isMultiLineDeclaration() + + + /** + * Processes single-line declarations. + * + * Just uses the Generic BSD-Allman brace sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $sniff = new OpeningFunctionBraceKernighanRitchieSniff(); + } else { + $sniff = new OpeningFunctionBraceBsdAllmanSniff(); + } + + $sniff->checkClosures = true; + $sniff->process($phpcsFile, $stackPtr); + + }//end processSingleLineDeclaration() + + + /** + * Processes multi-line declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + $this->processArgumentList($phpcsFile, $stackPtr, $this->indent); + + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$open]['parenthesis_closer']; + } + } + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // The opening brace needs to be one space away from the closing parenthesis. + $opener = $tokens[$stackPtr]['scope_opener']; + if ($tokens[$opener]['line'] !== $tokens[$closeBracket]['line']) { + $error = 'The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'NewlineBeforeOpenBrace'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), $closeBracket, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prev, ' {'); + + // If the opener is on a line by itself, removing it will create + // an empty line, so just remove the entire line instead. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $closeBracket, true); + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + + if ($tokens[$prev]['line'] < $tokens[$opener]['line'] + && $tokens[$next]['line'] > $tokens[$opener]['line'] + ) { + // Clear the whole line. + for ($i = ($prev + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else { + // Just remove the opener. + $phpcsFile->fixer->replaceToken($opener, ''); + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $phpcsFile->fixer->replaceToken(($opener + 1), ''); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $prev = $tokens[($opener - 1)]; + if ($prev['code'] !== T_WHITESPACE) { + $length = 0; + } else { + $length = strlen($prev['content']); + } + + if ($length !== 1) { + $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found %s spaces'; + $fix = $phpcsFile->addFixableError($error, ($opener - 1), 'SpaceBeforeOpenBrace', [$length]); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContentBefore($opener, ' '); + } else { + $phpcsFile->fixer->replaceToken(($opener - 1), ' '); + } + } + + return; + }//end if + }//end if + + }//end processMultiLineDeclaration() + + + /** + * Processes multi-line argument list declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $indent The number of spaces code should be indented. + * @param string $type The type of the token the brackets + * belong to. + * + * @return void + */ + public function processArgumentList($phpcsFile, $stackPtr, $indent, $type='function') + { + $tokens = $phpcsFile->getTokens(); + + // We need to work out how far indented the function + // declaration itself is, so we can work out how far to + // indent parameters. + $functionIndent = 0; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + break; + } + } + + // Move $i back to the line the function is or to 0. + $i++; + + if ($tokens[$i]['code'] === T_WHITESPACE) { + $functionIndent = $tokens[$i]['length']; + } + + // The closing parenthesis must be on a new line, even + // when checking abstract function definitions. + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + $prev = $phpcsFile->findPrevious( + T_WHITESPACE, + ($closeBracket - 1), + null, + true + ); + + if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line'] + && $tokens[$prev]['line'] === $tokens[$closeBracket]['line'] + ) { + $error = 'The closing parenthesis of a multi-line '.$type.' declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } + } + + // If this is a closure and is using a USE statement, the closing + // parenthesis we need to look at from now on is the closing parenthesis + // of the USE statement. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$open]['parenthesis_closer']; + + $prev = $phpcsFile->findPrevious( + T_WHITESPACE, + ($closeBracket - 1), + null, + true + ); + + if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line'] + && $tokens[$prev]['line'] === $tokens[$closeBracket]['line'] + ) { + $error = 'The closing parenthesis of a multi-line use declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'UseCloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } + } + }//end if + }//end if + + // Each line between the parenthesis should be indented 4 spaces. + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $lastLine = $tokens[$openBracket]['line']; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if ($tokens[$i]['line'] !== $lastLine) { + if ($i === $tokens[$stackPtr]['parenthesis_closer'] + || ($tokens[$i]['code'] === T_WHITESPACE + && (($i + 1) === $closeBracket + || ($i + 1) === $tokens[$stackPtr]['parenthesis_closer'])) + ) { + // Closing braces need to be indented to the same level + // as the function. + $expectedIndent = $functionIndent; + } else { + $expectedIndent = ($functionIndent + $indent); + } + + // We changed lines, so this should be a whitespace indent token. + $foundIndent = 0; + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'Blank lines are not allowed in a multi-line '.$type.' declaration'; + $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // This is an empty line, so don't check the indent. + continue; + } else if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundIndent = $tokens[$i]['length']; + } else if ($tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE) { + $foundIndent = $tokens[$i]['length']; + ++$expectedIndent; + } + + if ($expectedIndent !== $foundIndent) { + $error = 'Multi-line '.$type.' declaration not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $spaces); + } else { + $phpcsFile->fixer->replaceToken($i, $spaces); + } + } + } + + $lastLine = $tokens[$i]['line']; + }//end if + + if ($tokens[$i]['code'] === T_ARRAY || $tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + // Skip arrays as they have their own indentation rules. + if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + $i = $tokens[$i]['bracket_closer']; + } else { + $i = $tokens[$i]['parenthesis_closer']; + } + + $lastLine = $tokens[$i]['line']; + continue; + } + + if ($tokens[$i]['code'] === T_ATTRIBUTE) { + // Skip attributes as they have their own indentation rules. + $i = $tokens[$i]['attribute_closer']; + $lastLine = $tokens[$i]['line']; + continue; + } + }//end for + + }//end processArgumentList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php new file mode 100644 index 000000000..f13470789 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidDefaultValueSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Flag for when we have found a default in our arg list. + // If there is a value without a default after this, it is an error. + $defaultFound = false; + + $params = $phpcsFile->getMethodParameters($stackPtr); + foreach ($params as $param) { + if ($param['variable_length'] === true) { + continue; + } + + if (array_key_exists('default', $param) === true) { + $defaultFound = true; + // Check if the arg is type hinted and using NULL for the default. + // This does not make the argument optional - it just allows NULL + // to be passed in. + if ($param['type_hint'] !== '' && strtolower($param['default']) === 'null') { + $defaultFound = false; + } + + continue; + } + + if ($defaultFound === true) { + $error = 'Arguments with default values must be at the end of the argument list'; + $phpcsFile->addError($error, $param['token'], 'NotAtEnd'); + return; + } + }//end foreach + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php new file mode 100644 index 000000000..00e68bfec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidClassNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findNext(T_STRING, $stackPtr); + $name = trim($tokens[$className]['content']); + $errorData = [ucfirst($tokens[$stackPtr]['content'])]; + + // Make sure the first letter is a capital. + if (preg_match('|^[A-Z]|', $name) === 0) { + $error = '%s name must begin with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'StartWithCapital', $errorData); + } + + // Check that each new word starts with a capital as well, but don't + // check the first word, as it is checked above. + $validName = true; + $nameBits = explode('_', $name); + $firstBit = array_shift($nameBits); + foreach ($nameBits as $bit) { + if ($bit === '' || $bit[0] !== strtoupper($bit[0])) { + $validName = false; + break; + } + } + + if ($validName === false) { + // Strip underscores because they cause the suggested name + // to be incorrect. + $nameBits = explode('_', trim($name, '_')); + $firstBit = array_shift($nameBits); + if ($firstBit === '') { + $error = '%s name is not valid'; + $phpcsFile->addError($error, $stackPtr, 'Invalid', $errorData); + } else { + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $newName = rtrim($newName, '_'); + $error = '%s name is not valid; consider %s instead'; + $data = $errorData; + $data[] = $newName; + $phpcsFile->addError($error, $stackPtr, 'Invalid', $data); + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 000000000..e7f87d44d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,284 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidFunctionNameSniff extends AbstractScopeSniff +{ + + /** + * A list of all PHP magic methods. + * + * @var array + */ + protected $magicMethods = [ + 'construct' => true, + 'destruct' => true, + 'call' => true, + 'callstatic' => true, + 'get' => true, + 'set' => true, + 'isset' => true, + 'unset' => true, + 'sleep' => true, + 'wakeup' => true, + 'serialize' => true, + 'unserialize' => true, + 'tostring' => true, + 'invoke' => true, + 'set_state' => true, + 'clone' => true, + 'debuginfo' => true, + ]; + + /** + * A list of all PHP magic functions. + * + * @var array + */ + protected $magicFunctions = ['autoload' => true]; + + + /** + * Constructs a PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + + $methodNameLc = strtolower($methodName); + $classNameLc = strtolower($className); + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = substr($methodNameLc, 2); + if (isset($this->magicMethods[$magicPart]) === true) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); + } + + // PHP4 constructors are allowed to break our rules. + if ($methodNameLc === $classNameLc) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodNameLc === '_'.$classNameLc) { + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + $scope = $methodProps['scope']; + $scopeSpecified = $methodProps['scope_specified']; + + if ($methodProps['scope'] === 'private') { + $isPublic = false; + } else { + $isPublic = true; + } + + // If it's a private method, it must have an underscore on the front. + if ($isPublic === false) { + if ($methodName[0] !== '_') { + $error = 'Private method name "%s" must be prefixed with an underscore'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'yes'); + } + } + + // If it's not a private method, it must not have an underscore on the front. + if ($isPublic === true && $scopeSpecified === true && $methodName[0] === '_') { + $error = '%s method name "%s" must not be prefixed with an underscore'; + $data = [ + ucfirst($scope), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); + } + + $testMethodName = ltrim($methodName, '_'); + + if (Common::isCamelCaps($testMethodName, false, true, false) === false) { + if ($scopeSpecified === true) { + $error = '%s method name "%s" is not in camel caps format'; + $data = [ + ucfirst($scope), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); + } else { + $error = 'Method name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + if (ltrim($functionName, '_') === '') { + // Ignore special functions. + return; + } + + $errorData = [$functionName]; + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === true) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData); + } + + // Function names can be in two parts; the package name and + // the function name. + $packagePart = ''; + $underscorePos = strrpos($functionName, '_'); + if ($underscorePos === false) { + $camelCapsPart = $functionName; + } else { + $packagePart = substr($functionName, 0, $underscorePos); + $camelCapsPart = substr($functionName, ($underscorePos + 1)); + + // We don't care about _'s on the front. + $packagePart = ltrim($packagePart, '_'); + } + + // If it has a package part, make sure the first letter is a capital. + if ($packagePart !== '') { + if ($functionName[0] === '_') { + $error = 'Function name "%s" is invalid; only private methods should be prefixed with an underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionUnderscore', $errorData); + } + + if ($functionName[0] !== strtoupper($functionName[0])) { + $error = 'Function name "%s" is prefixed with a package name but does not begin with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'FunctionNoCapital', $errorData); + } + } + + // If it doesn't have a camel caps part, it's not valid. + if (trim($camelCapsPart) === '') { + $error = 'Function name "%s" is not valid; name appears incomplete'; + $phpcsFile->addError($error, $stackPtr, 'FunctionInvalid', $errorData); + return; + } + + $validName = true; + $newPackagePart = $packagePart; + $newCamelCapsPart = $camelCapsPart; + + // Every function must have a camel caps part, so check that first. + if (Common::isCamelCaps($camelCapsPart, false, true, false) === false) { + $validName = false; + $newCamelCapsPart = strtolower($camelCapsPart[0]).substr($camelCapsPart, 1); + } + + if ($packagePart !== '') { + // Check that each new word starts with a capital. + $nameBits = explode('_', $packagePart); + $nameBits = array_filter($nameBits); + foreach ($nameBits as $bit) { + if ($bit[0] !== strtoupper($bit[0])) { + $newPackagePart = ''; + foreach ($nameBits as $bit) { + $newPackagePart .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + + $validName = false; + break; + } + } + } + + if ($validName === false) { + if ($newPackagePart === '') { + $newName = $newCamelCapsPart; + } else { + $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart; + } + + $error = 'Function name "%s" is invalid; consider "%s" instead'; + $data = $errorData; + $data[] = $newName; + $phpcsFile->addError($error, $stackPtr, 'FunctionNameInvalid', $data); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..89af5df8e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + return; + } + + $memberName = ltrim($tokens[$stackPtr]['content'], '$'); + $scope = $memberProps['scope']; + $scopeSpecified = $memberProps['scope_specified']; + + if ($memberProps['scope'] === 'private') { + $isPublic = false; + } else { + $isPublic = true; + } + + // If it's a private member, it must have an underscore on the front. + if ($isPublic === false && $memberName[0] !== '_') { + $error = 'Private member variable "%s" must be prefixed with an underscore'; + $data = [$memberName]; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); + return; + } + + // If it's not a private member, it must not have an underscore on the front. + if ($isPublic === true && $scopeSpecified === true && $memberName[0] === '_') { + $error = '%s member variable "%s" must not be prefixed with an underscore'; + $data = [ + ucfirst($scope), + $memberName, + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); + return; + } + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php new file mode 100644 index 000000000..fb1b79a32 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php @@ -0,0 +1,204 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ObjectOperatorIndentSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * Indicates whether multilevel indenting is allowed. + * + * @var boolean + */ + public $multilevel = false; + + /** + * Tokens to listen for. + * + * @var array + */ + private $targets = [ + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return $this->targets; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is the first object operator in a chain of them. + $start = $phpcsFile->findStartOfStatement($stackPtr); + $prev = $phpcsFile->findPrevious($this->targets, ($stackPtr - 1), $start); + if ($prev !== false) { + return; + } + + // Make sure this is a chained call. + $end = $phpcsFile->findEndOfStatement($stackPtr); + $next = $phpcsFile->findNext($this->targets, ($stackPtr + 1), $end); + if ($next === false) { + // Not a chained call. + return; + } + + // Determine correct indent. + for ($i = ($start - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$start]['line']) { + $i++; + break; + } + } + + $baseIndent = 0; + if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) { + $baseIndent = $tokens[$i]['length']; + } + + $baseIndent += $this->indent; + + // Determine the scope of the original object operator. + $origBrackets = null; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $origBrackets = $tokens[$stackPtr]['nested_parenthesis']; + } + + $origConditions = null; + if (isset($tokens[$stackPtr]['conditions']) === true) { + $origConditions = $tokens[$stackPtr]['conditions']; + } + + // Check indentation of each object operator in the chain. + // If the first object operator is on a different line than + // the variable, make sure we check its indentation too. + if ($tokens[$stackPtr]['line'] > $tokens[$start]['line']) { + $next = $stackPtr; + } + + $previousIndent = $baseIndent; + + while ($next !== false) { + // Make sure it is in the same scope, otherwise don't check indent. + $brackets = null; + if (isset($tokens[$next]['nested_parenthesis']) === true) { + $brackets = $tokens[$next]['nested_parenthesis']; + } + + $conditions = null; + if (isset($tokens[$next]['conditions']) === true) { + $conditions = $tokens[$next]['conditions']; + } + + if ($origBrackets === $brackets && $origConditions === $conditions) { + // Make sure it starts a line, otherwise don't check indent. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), $stackPtr, true); + $indent = $tokens[($next - 1)]; + if ($tokens[$prev]['line'] !== $tokens[$next]['line'] + && $indent['code'] === T_WHITESPACE + ) { + if ($indent['line'] === $tokens[$next]['line']) { + $foundIndent = strlen($indent['content']); + } else { + $foundIndent = 0; + } + + $minIndent = $previousIndent; + $maxIndent = $previousIndent; + $expectedIndent = $previousIndent; + + if ($this->multilevel === true) { + $minIndent = max(($previousIndent - $this->indent), $baseIndent); + $maxIndent = ($previousIndent + $this->indent); + $expectedIndent = min(max($foundIndent, $minIndent), $maxIndent); + } + + if ($foundIndent < $minIndent || $foundIndent > $maxIndent) { + $error = 'Object operator not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $next, 'Incorrect', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($next, $spaces); + } else { + $phpcsFile->fixer->replaceToken(($next - 1), $spaces); + } + } + } + + $previousIndent = $expectedIndent; + }//end if + + // It cant be the last thing on the line either. + $content = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$content]['line'] !== $tokens[$next]['line']) { + $error = 'Object operator must be at the start of the line, not the end'; + $fix = $phpcsFile->addFixableError($error, $next, 'StartOfLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($next + 1); $x < $content; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewlineBefore($next); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + $next = $phpcsFile->findNext( + $this->targets, + ($next + 1), + null, + false, + null, + true + ); + }//end while + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php new file mode 100644 index 000000000..097754e57 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @@ -0,0 +1,179 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeClosingBraceSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return Tokens::$scopeOpeners; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + // If the scope closer doesn't think it belongs to this scope opener + // then the opener is sharing its closer with other tokens. We only + // want to process the closer once, so skip this one. + if (isset($tokens[$scopeEnd]['scope_condition']) === false + || $tokens[$scopeEnd]['scope_condition'] !== $stackPtr + ) { + return; + } + + // We need to actually find the first piece of content on this line, + // because if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = ($stackPtr - 1); + for ($lineStart; $lineStart > 0; $lineStart--) { + if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + + $lineStart++; + + $startColumn = 1; + if ($tokens[$lineStart]['code'] === T_WHITESPACE) { + $startColumn = $tokens[($lineStart + 1)]['column']; + } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) { + $trimmed = ltrim($tokens[$lineStart]['content']); + if ($trimmed === '') { + $startColumn = $tokens[($lineStart + 1)]['column']; + } else { + $startColumn = (strlen($tokens[$lineStart]['content']) - strlen($trimmed)); + } + } + + // Check that the closing brace is on it's own line. + $lastContent = $phpcsFile->findPrevious( + [ + T_WHITESPACE, + T_INLINE_HTML, + T_OPEN_TAG, + ], + ($scopeEnd - 1), + $scopeStart, + true + ); + + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) { + $error = 'Closing brace must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Line'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($scopeEnd); + } + + return; + } + + // Check now that the closing brace is lined up correctly. + $lineStart = ($scopeEnd - 1); + for ($lineStart; $lineStart > 0; $lineStart--) { + if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + + $lineStart++; + + $braceIndent = 0; + if ($tokens[$lineStart]['code'] === T_WHITESPACE) { + $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1); + } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) { + $trimmed = ltrim($tokens[$lineStart]['content']); + if ($trimmed === '') { + $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1); + } else { + $braceIndent = (strlen($tokens[$lineStart]['content']) - strlen($trimmed) - 1); + } + } + + $fix = false; + if ($tokens[$stackPtr]['code'] === T_CASE + || $tokens[$stackPtr]['code'] === T_DEFAULT + ) { + // BREAK statements should be indented n spaces from the + // CASE or DEFAULT statement. + $expectedIndent = ($startColumn + $this->indent - 1); + if ($braceIndent !== $expectedIndent) { + $error = 'Case breaking statement indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $braceIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'BreakIndent', $data); + } + } else { + $expectedIndent = max(0, ($startColumn - 1)); + if ($braceIndent !== $expectedIndent) { + $error = 'Closing brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $braceIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data); + } + }//end if + + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($braceIndent === 0) { + $phpcsFile->fixer->addContentBefore($lineStart, $spaces); + } else { + $phpcsFile->fixer->replaceToken($lineStart, ltrim($tokens[$lineStart]['content'])); + $phpcsFile->fixer->addContentBefore($lineStart, $spaces); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php new file mode 100644 index 000000000..2620d20f2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -0,0 +1,24 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ScopeIndentSniff as GenericScopeIndentSniff; + +class ScopeIndentSniff extends GenericScopeIndentSniff +{ + + /** + * Any scope openers that should not cause an indent. + * + * @var int[] + */ + protected $nonIndentingScopes = [T_SWITCH]; + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc new file mode 100644 index 000000000..6942944b5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc @@ -0,0 +1,114 @@ +setLogger(new class {}); + +var_dump(new class(10) extends SomeClass implements SomeInterface { + private $num; + + public function __construct($num) + { + $this->num = $num; + } + + use SomeTrait; +}); + +class IncorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration /* Comment */ { +} + +class CorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration +/* Comment */ +{ +} + +// Don't move phpcs:ignore comments. +class PHPCSIgnoreAnnotationAfterOpeningBrace +{ // phpcs:ignore Standard.Cat.Sniff -- for reasons. +} + +// Moving any of the other trailing phpcs: comments is ok. +class PHPCSAnnotationAfterOpeningBrace +{ // phpcs:disable Standard.Cat.Sniff -- for reasons. +} + +if (!class_exists('ClassOpeningBraceShouldBeIndented')) { + abstract class ClassOpeningBraceShouldBeIndented +{ +} +} + +if (!class_exists('ClassOpeningBraceTooMuchIndentation')) { + final class ClassOpeningBraceTooMuchIndentation + { + } +} + +enum IncorrectBracePlacement {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed new file mode 100644 index 000000000..26688b152 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,125 @@ +setLogger(new class {}); + +var_dump(new class(10) extends SomeClass implements SomeInterface { + private $num; + + public function __construct($num) + { + $this->num = $num; + } + + use SomeTrait; +}); + +class IncorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration /* Comment */ +{ +} + +class CorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration +/* Comment */ +{ +} + +// Don't move phpcs:ignore comments. +class PHPCSIgnoreAnnotationAfterOpeningBrace +{ // phpcs:ignore Standard.Cat.Sniff -- for reasons. +} + +// Moving any of the other trailing phpcs: comments is ok. +class PHPCSAnnotationAfterOpeningBrace +{ + // phpcs:disable Standard.Cat.Sniff -- for reasons. +} + +if (!class_exists('ClassOpeningBraceShouldBeIndented')) { + abstract class ClassOpeningBraceShouldBeIndented + { +} +} + +if (!class_exists('ClassOpeningBraceTooMuchIndentation')) { + final class ClassOpeningBraceTooMuchIndentation + { + } +} + +enum IncorrectBracePlacement +{ +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc new file mode 100644 index 000000000..ac71fc9f2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc @@ -0,0 +1,11 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'ClassDeclarationUnitTest.1.inc') { + return; + } + + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClassDeclarationUnitTest.1.inc': + return [ + 21 => 1, + 22 => 1, + 23 => 1, + 27 => 1, + 33 => 1, + 38 => 1, + 49 => 1, + 84 => 1, + 94 => 1, + 99 => 1, + 104 => 1, + 110 => 1, + 114 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'ClassDeclarationUnitTest.2.inc') { + return [11 => 1]; + } + + return[]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc new file mode 100644 index 000000000..da53b99e8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc @@ -0,0 +1,145 @@ + + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: 1.0 + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Extra_Description_Newlines +{ + +}//end class + + +/** + * Sample class comment + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Missing_Newlines_Before_Tags +{ + +}//end class + + +/** + * Simple class comment + * + * @category _wrong_category + * @package PHP_CodeSniffer + * @package ADDITIONAL PACKAGE TAG + * @subpackage SUBPACKAGE TAG + * @author Original Author + * @author Greg Sherwood gsherwood@squiz.net + * @author Mr T + * @author + * @copyright 1997~1994 The PHP Group + * @license http://www.php.net/license/3_0.txt + * @version INVALID VERSION CONTENT + * @see + * @see + * @link sdfsdf + * @see Net_Sample::Net_Sample() + * @see Net_Other + * @deprecated asd + * @unknown Unknown tag + * @since Class available since Release 1.2.0 + */ +class Checking_Tags +{ + class Sub_Class { + + }//end class + + +}//end class + + +/** + * + * + */ +class Empty_Class_Doc +{ + +}//end class + + +/** + * + * + */ +interface Empty_Interface_Doc +{ + +}//end interface + + +/** + * + * + */ +trait Empty_Trait_Doc +{ + +}//end trait + + +/** + * + * + */ +enum Empty_Enum_Doc +{ + +}//end enum + + +/** + * Sample class comment + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +#[Authenticate('admin_logged_in')] +class TodoController extends AbstractController implements MustBeLoggedInInterface +{ +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php new file mode 100644 index 000000000..004a064b3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 15 => 1, + 51 => 1, + 63 => 1, + 65 => 2, + 66 => 1, + 68 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 74 => 2, + 75 => 1, + 76 => 1, + 77 => 1, + 85 => 1, + 96 => 5, + 106 => 5, + 116 => 5, + 126 => 5, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 71 => 1, + 73 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc new file mode 100644 index 000000000..0b18fa38a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc @@ -0,0 +1,53 @@ + +* @author Greg Sherwood gsherwood@squiz.net +* @author Mr T +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1997~1994 The PHP Group +* @license http://www.php.net/license/3_0.txt +* @see +* @see +* @version INVALID VERSION CONTENT +* @see Net_Sample::Net_Sample() +* @see Net_Other +* @deprecated asd +* @since Class available since Release 1.2.0 +* @summary An unknown summary tag +* @package '' +* @subpackage !! +* @author Code AUthor +*/ +require_once '/some/path.php'; +?> + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc new file mode 100644 index 000000000..8845eb190 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FileCommentUnitTest.inc') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + return [ + 21 => 1, + 23 => 2, + 24 => 1, + 26 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 2, + 33 => 1, + 34 => 1, + 35 => 1, + 40 => 2, + 41 => 2, + 43 => 1, + ]; + + case 'FileCommentUnitTest.2.inc': + return [1 => 1]; + + case 'FileCommentUnitTest.3.inc': + return [1 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='FileCommentUnitTest.inc') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + return [ + 29 => 1, + 30 => 1, + 34 => 1, + 43 => 1, + ]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 000000000..5c3295fd6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,478 @@ + line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function foo(&$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Gettext. + * + */ +function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Complete a step. + * + * @param string $status Status of step to complete. + * @param array $array Array. + * @param string $note Optional note. + * + * @return void + */ +function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { + echo 'foo'; +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + +/** + * Completely invalid format, but should not cause PHP notices. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Processes the test. + * + * @param PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * Processes the test. + * + * @param int $phpcsFile The PHP_CodeSniffer + * file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * @param (Foo&Bar)|null $a Comment. + * @param string $b Comment. + * + * @return void + */ +public function setTranslator($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility protected +private function setTranslator2($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility public +protected function setTranslator3($a, &$b): void +{ + $this->translator = $translator; +} + +private function setTranslator4($a, &$b): void +{ + $this->translator = $translator; +} + +class Bar { + /** + * The PHP5 constructor + * + * @return + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] __construct,__destruct + +class Something implements JsonSerializable { + /** + * Single attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function jsonSerialize() {} + + /** + * Multiple attributes. + * + * @return Something + */ + #[AttributeA] + #[AttributeB] + public function methodName() {} + + /** + * Blank line between docblock and attribute. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + public function blankLineDetectionA() {} + + /** + * Blank line between attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + + public function blankLineDetectionB() {} + + /** + * Blank line between both docblock and attribute and attribute and function declaration. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + + public function blankLineDetectionC() {} +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed new file mode 100644 index 000000000..751b09c66 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed @@ -0,0 +1,478 @@ + line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function foo(&$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Gettext. + * + */ +function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Complete a step. + * + * @param string $status Status of step to complete. + * @param array $array Array. + * @param string $note Optional note. + * + * @return void + */ +function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { + echo 'foo'; +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + +/** + * Completely invalid format, but should not cause PHP notices. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Processes the test. + * + * @param PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * Processes the test. + * + * @param int $phpcsFile The PHP_CodeSniffer + * file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * @param (Foo&Bar)|null $a Comment. + * @param string $b Comment. + * + * @return void + */ +public function setTranslator($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility protected +private function setTranslator2($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility public +protected function setTranslator3($a, &$b): void +{ + $this->translator = $translator; +} + +private function setTranslator4($a, &$b): void +{ + $this->translator = $translator; +} + +class Bar { + /** + * The PHP5 constructor + * + * @return + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] __construct,__destruct + +class Something implements JsonSerializable { + /** + * Single attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function jsonSerialize() {} + + /** + * Multiple attributes. + * + * @return Something + */ + #[AttributeA] + #[AttributeB] + public function methodName() {} + + /** + * Blank line between docblock and attribute. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + public function blankLineDetectionA() {} + + /** + * Blank line between attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + + public function blankLineDetectionB() {} + + /** + * Blank line between both docblock and attribute and attribute and function declaration. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + + public function blankLineDetectionC() {} +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 000000000..734ff73e5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,96 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 28 => 1, + 76 => 1, + 87 => 1, + 103 => 1, + 109 => 1, + 112 => 1, + 122 => 1, + 123 => 2, + 124 => 2, + 125 => 1, + 126 => 1, + 137 => 1, + 138 => 1, + 139 => 1, + 152 => 1, + 155 => 1, + 165 => 1, + 172 => 1, + 183 => 1, + 190 => 2, + 206 => 1, + 234 => 1, + 272 => 1, + 313 => 1, + 317 => 1, + 327 => 1, + 329 => 1, + 332 => 1, + 344 => 1, + 343 => 1, + 345 => 1, + 346 => 1, + 360 => 1, + 361 => 1, + 363 => 1, + 364 => 1, + 406 => 1, + 417 => 1, + 455 => 1, + 464 => 1, + 473 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc new file mode 100644 index 000000000..187228c2a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc @@ -0,0 +1,29 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InlineCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 15 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc new file mode 100644 index 000000000..cc9903aa1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc @@ -0,0 +1,165 @@ + 0); + +do +{ + echo $i; +} while ($i > 0); + +do +{ + echo $i; +} +while ($i > 0); + +do { echo $i; } while ($i > 0); + +do{ + echo $i; +}while($i > 0); + + +// while +while ($i < 1) { + echo $i; +} + +while($i < 1){ + echo $i; +} + +while ($i < 1) { echo $i; } + + +// for +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for($i = 1; $i < 1; $i++){ + echo $i; +} + +for ($i = 1; $i < 1; $i++) { echo $i; } + + +// foreach +foreach ($items as $item) { + echo $item; +} + +foreach($items as $item){ + echo $item; +} + +foreach ($items as $item) { echo $item; } + + +// if +if ($i == 0) { + $i = 1; +} + +if($i == 0){ + $i = 1; +} + +if ($i == 0) { $i = 1; } + + +// else +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + + +// else +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + + +// else if +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} elseif ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else if($i == 2){ + $i = 0; +} + +if ($i == 0) { + $i = 1; +}elseif($i == 2){ + $i = 0; +} + +if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; } +if ($i == 0) { $i = 1; } elseif ($i == 2) { $i = 0; } + +if ($i == 0) { // this is ok because comments are allowed + $i = 1; +} + +if ($i == 0) {// this is ok because comments are allowed + $i = 1; +} + +if ($i == 0) { /* this is ok because comments are allowed*/ + $i = 1; +} + +if ($i == 0) +{ // this is not ok + $i = 1; +} + +if ($i == 0) /* this is ok */ { +} + +if ($i == 0) { +} +else { +} + +// match +$r = match ($x) { + 1 => 1, +}; + +$r = match( $x ){ 1 => 1 }; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php new file mode 100644 index 000000000..98c3463b7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 14 => 1, + 20 => 1, + 22 => 1, + 32 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 56 => 1, + 60 => 1, + 68 => 1, + 72 => 1, + 84 => 1, + 88 => 2, + 100 => 1, + 104 => 2, + 122 => 2, + 128 => 1, + 132 => 3, + 133 => 2, + 147 => 1, + 157 => 1, + 165 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc new file mode 100644 index 000000000..a7a3c69d7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc @@ -0,0 +1,251 @@ + +

some text

+errorCode() == 401 || // comment + $IPP->errorCode() == 3200) /* long comment + here + */ +{ + return false; +} + +if ($IPP->errorCode() == 401 || // comment + $IPP->errorCode() == 3200) // long comment here +{ + return false; +} + +if ($IPP->errorCode() == 401 + // Comment explaining the next condition here. + || $IPP->errorCode() == 3200 +) { + return false; +} + +function bar() { + if ($a + && $b +) { + return false; + } +} + +if ($a + && foo( + 'a', + 'b' + )) { + return false; +} + +?> + + + + + +errorCode() == 401 || // phpcs:ignore Standard.Category.Sniff -- for reasons. + $IPP->errorCode() == 3200) /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +{ + return false; +} + +if ($IPP->errorCode() == 401 || // phpcs:disable Standard.Category.Sniff -- for reasons. + $IPP->errorCode() == 3200) // phpcs:enable +{ + return false; +} + +if ($IPP->errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 +) { + return false; +} + + if ($IPP->errorCode() == 401 || + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + $IPP->errorCode() == 3200 + ) { + return false; + } + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // A comment. + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + === 'someverylongexpectedoutput' +) { + return false; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed new file mode 100644 index 000000000..7d56c4618 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed @@ -0,0 +1,247 @@ + +

some text

+errorCode() == 401 // comment + || $IPP->errorCode() == 3200 /* long comment + here + */ +) { + return false; +} + +if ($IPP->errorCode() == 401 // comment + || $IPP->errorCode() == 3200 // long comment here +) { + return false; +} + +if ($IPP->errorCode() == 401 + // Comment explaining the next condition here. + || $IPP->errorCode() == 3200 +) { + return false; +} + +function bar() { + if ($a + && $b + ) { + return false; + } +} + +if ($a + && foo( + 'a', + 'b' + ) +) { + return false; +} + +?> + + + + + +errorCode() == 401 // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +) { + return false; +} + +if ($IPP->errorCode() == 401 // phpcs:disable Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 // phpcs:enable +) { + return false; +} + +if ($IPP->errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 +) { + return false; +} + + if ($IPP->errorCode() == 401 + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + || $IPP->errorCode() == 3200 + ) { + return false; + } + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // A comment. + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + === 'someverylongexpectedoutput' +) { + return false; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js new file mode 100644 index 000000000..064d7ff7a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js @@ -0,0 +1,251 @@ +if (blah(param)) { + +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if ((condition1 || condition2) && condition3 && condition4 && condition5) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ( + (condition1 || condition2) + && condition3 +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 && + condition4 +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if (($condition1 + || $condition2) +) { +} + +if ((condition1 + || condition2) + ) { +} + +if ( + ( + condition1 + || condition2 + ) + && condition3 +) { +} + + +if ( condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if ( + condition1 + || condition2 && + condition3 +) { +} + +if (condition1 + || condition2 +|| condition3) { +} + +if (condition1 + || condition2 || condition3 +){ +} + +if (condition1) + console.info('bar'); + +if (condition1 + || condition2 +|| condition3) + console.info('bar'); + + +if (condition1 + || condition2 || condition3 +) + console.info('bar'); + +if (!a(post) + && (!a(context.header) + ^ a(context.header, 'Content-Type')) +) { +// ... +} + +if (foo) +{ + console.info('bar'); +} + +// Should be no errors even though lines are +// not exactly aligned together. Multi-line function +// call takes precedence. +if (array_key_exists(key, value) + && foo.bar.baz( + key, value2 + ) +) { +} + +if (true) { + foo = true; +}; + +if (foo == 401 || // comment + bar == 3200) /* long comment + here + */ +{ + return false; +} + +if (foo == 401 || // comment + bar == 3200) // long comment here +{ + return false; +} + +if (IPP.errorCode() == 401 + // Comment explaining the next condition here. + || IPP.errorCode() == 3200 +) { + return false; +} + +function bar() { + if (a + && b +) { + return false; + } +} + +if (a + && foo( + 'a', + 'b' + )) { + return false; +} + + + + + + + + + + + + + +if (foo == 401 || // phpcs:ignore Standard.Category.Sniff -- for reasons. + bar == 3200) /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +{ + return false; +} + +if (foo == 401 || // phpcs:disable Standard.Category.Sniff -- for reasons. + bar == 3200) // phpcs:enable +{ + return false; +} + +if (IPP.errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || IPP.errorCode() == 3200 +) { + return false; +} + + if (foo == 401 || + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + bar == 3200 + ) { + return false; + } + +if (IPP.errorCode() == 401 + || IPP.errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if (foo == 401 + || bar + == 'someverylongexpectedoutput' +) { + return false; +} + +if (IPP.errorCode() == 401 + || bar + // A comment. + == 'someverylongexpectedoutput' +) { + return false; +} + +if (foo == 401 + || IPP.errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + == 'someverylongexpectedoutput' +) { + return false; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed new file mode 100644 index 000000000..cfde75d74 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed @@ -0,0 +1,247 @@ +if (blah(param)) { + +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if ((condition1 || condition2) && condition3 && condition4 && condition5) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if (($condition1 + || $condition2) +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 +) { +} + + +if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + && condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 || condition3 +) { +} + +if (condition1) + console.info('bar'); + +if (condition1 + || condition2 + || condition3 +) + console.info('bar'); + + +if (condition1 + || condition2 || condition3 +) + console.info('bar'); + +if (!a(post) + && (!a(context.header) + ^ a(context.header, 'Content-Type')) +) { +// ... +} + +if (foo) { + console.info('bar'); +} + +// Should be no errors even though lines are +// not exactly aligned together. Multi-line function +// call takes precedence. +if (array_key_exists(key, value) + && foo.bar.baz( + key, value2 + ) +) { +} + +if (true) { + foo = true; +}; + +if (foo == 401 // comment + || bar == 3200 /* long comment + here + */ +) { + return false; +} + +if (foo == 401 // comment + || bar == 3200 // long comment here +) { + return false; +} + +if (IPP.errorCode() == 401 + // Comment explaining the next condition here. + || IPP.errorCode() == 3200 +) { + return false; +} + +function bar() { + if (a + && b + ) { + return false; + } +} + +if (a + && foo( + 'a', + 'b' + ) +) { + return false; +} + + + + + + + + + + + + + +if (foo == 401 // phpcs:ignore Standard.Category.Sniff -- for reasons. + || bar == 3200 /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +) { + return false; +} + +if (foo == 401 // phpcs:disable Standard.Category.Sniff -- for reasons. + || bar == 3200 // phpcs:enable +) { + return false; +} + +if (IPP.errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || IPP.errorCode() == 3200 +) { + return false; +} + + if (foo == 401 + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + || bar == 3200 + ) { + return false; + } + +if (IPP.errorCode() == 401 + || IPP.errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if (foo == 401 + || bar == 'someverylongexpectedoutput' +) { + return false; +} + +if (IPP.errorCode() == 401 + || bar + // A comment. + == 'someverylongexpectedoutput' +) { + return false; +} + +if (foo == 401 + || IPP.errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + == 'someverylongexpectedoutput' +) { + return false; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php new file mode 100644 index 000000000..f78b4e3f3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MultiLineConditionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='MultiLineConditionUnitTest.inc') + { + $errors = [ + 21 => 1, + 22 => 1, + 35 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 49 => 1, + 54 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 67 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + 90 => 1, + 96 => 2, + 101 => 1, + 109 => 2, + 125 => 1, + 145 => 2, + 153 => 2, + 168 => 1, + 177 => 1, + 194 => 2, + 202 => 2, + 215 => 1, + 218 => 2, + 232 => 2, + 239 => 1, + 240 => 2, + 248 => 2, + ]; + + if ($testFile === 'MultiLineConditionUnitTest.inc') { + $errors[183] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc new file mode 100644 index 000000000..dadfe9234 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc @@ -0,0 +1,99 @@ + +
+Some content goes here.
+
+
+ +
+    Some content goes here.
+    
+    
+ +
+Some content goes here.
+
+
+ +
+    Some content goes here.
+    
+    
+ + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncludingFileUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 11 => 1, + 12 => 1, + 16 => 1, + 17 => 1, + 33 => 1, + 34 => 1, + 47 => 1, + 48 => 1, + 64 => 1, + 65 => 1, + 73 => 1, + 74 => 1, + 85 => 1, + 86 => 1, + 98 => 1, + 99 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc new file mode 100644 index 000000000..fc6aea006 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc @@ -0,0 +1,22 @@ +additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = + $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = 'boo'; + +$var='string'; + +function getInstalledStandards( + $includeGeneric=false, + $standardsDir='' +) { +} +?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php new file mode 100644 index 000000000..734d4fce8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Formatting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MultiLineAssignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 6 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc new file mode 100644 index 000000000..ed3d2c43e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc @@ -0,0 +1,550 @@ +getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +$var = myFunction( +$foo, +$bar +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +fputs( + STDOUT, + "Examples: + $ {$app} , --all + $ {$app} --all", $something +); + +$array = array(); +array_map( + function($x) + { + return trim($x, $y); + }, $foo, + $array +); + +$bar = new stdClass( + 4, /* thanks */ 5, /* PSR-2 */ 6 +); + +function doSomething() +{ + return $this->getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +doError( + 404, // status code + 'Not Found', // error name + 'Check your id' // fix +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +// Don't report errors for closing braces. Leave that to other sniffs. +foo( + [ + 'this', + 'is', + 'an', + 'array' + ], +[ + 'this', + 'is', + 'an', + 'array' + ], + array( + 'this', + 'is', +'an', +'array' + ), + array( + 'this', + 'is', + 'an', + 'array' + ), + function($x) + { + echo 'wee'; + + return trim($x); + } +); + +function foo() +{ + myFunction( + 'string'. + // comment + // comment + 'string'. + /* comment + * comment + */ + 'string' + ); +} + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test($arg, $arg2); +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test(); +test( ); +test( ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +?> + + + +
  • + log(// ... + 'error', + sprintf( + 'Message: %s', + isset($e->getData()['object']['evidence_details']) + ? $e->getData()['object']['evidence_details']['due_by'] + : '' + ), + array($e->getData()['object']) +); + +?> +
    + $class + ] + ); ?> +
    + + function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +array_filter( + [1, 2], + function ($i) : bool { + return $i === 0; + } +); + +foo(array( + 'callback' => function () { + $foo = 'foo'; + return; + }, +)); + +foo( + $a, + /* + $c, + + $d, + */ + $e +); + +test( + 1,2,3,4 + ); + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a','b', 'c' + ); + } +} + +$x = $var('y', +'x'); + +$obj->{$x}(1, + 2); + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)('c', + 'd'); + +class Foo +{ + public function bar($a, $b) + { + if (!$a || !$b) { + return; + } + + (new stdClass())->a = $a; + } +} + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})('a','b')('c','d'); + +function foo() +{ + Bar( + function () { + } + ); +} + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 7 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 9 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +printf( + '', + $obj->getName(), // Trailing comment. + $obj->getID(), // phpcs:ignore Standard.Category.SniffName -- for reasons. + $option +); + +// Handling of PHP 7.3 trailing comma's. +functionCall($args, $foo,); +functionCall( + $args, $foo, +); +functionCall( + $args, + $foo, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +$this->foo( + + ['a','b'], + true + +); + +$this->foo( + + // Comment + ['a','b'], + true + +); + +function m() +{ + $t = ' + ' . (empty(true) ? ' + ' . f( + '1', + '2', + ) . ' + ' : ''); +} + +class C +{ + + public function m() + { + $a = []; + $t = + "SELECT * FROM t +WHERE f IN(" . implode( + ",", + $a + ) . ")"; + } +} + +$notices = array( + 'index' => sprintf( + translation_function('a text string with %s placeholder'), + 'replacement' + ), +); + +$componentType = $this->componentTypeRepository->findByType($this->identifier) ?: + $this->componentTypeFactory->createForType( + $this->identifier, + $this->className, + true, + $this->isPrototypal + ); + +return [ + 'export-path' => 'exports/database/' + . env( + 'APP_CUSTOMER', + 'not-configured' + ) + . '/' . env( + 'APP_IDENTIFIER', + 'not-configured' + ), +]; + +$methods .= + str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate + ) + . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + +$rangeValues['min'] = + $this->adjustLowerThreshold( + $this->normalizeRatingForFilter($rangeValues['min']) + ); + +$salesOrderThresholdTransfer->fromArray($salesOrderThresholdEntity->toArray(), true) + ->setSalesOrderThresholdValue( + $this->mapSalesOrderThresholdValueTransfer($salesOrderThresholdTransfer, $salesOrderThresholdEntity) + )->setCurrency( + (new CurrencyTransfer())->fromArray($salesOrderThresholdEntity->getCurrency()->toArray(), true) + )->setStore( + (new StoreTransfer())->fromArray($salesOrderThresholdEntity->getStore()->toArray(), true) + ); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + )); + +$a = ['a' => function ($b) { return $b; }]; +$a['a']( 1 ); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed new file mode 100644 index 000000000..8d02e7467 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed @@ -0,0 +1,565 @@ +getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +$var = myFunction( + $foo, + $bar +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +fputs( + STDOUT, + "Examples: + $ {$app} , --all + $ {$app} --all", + $something +); + +$array = array(); +array_map( + function($x) + { + return trim($x, $y); + }, + $foo, + $array +); + +$bar = new stdClass( + 4, /* thanks */ + 5, /* PSR-2 */ + 6 +); + +function doSomething() +{ + return $this->getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +doError( + 404, // status code + 'Not Found', // error name + 'Check your id' // fix +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +// Don't report errors for closing braces. Leave that to other sniffs. +foo( + [ + 'this', + 'is', + 'an', + 'array' + ], + [ + 'this', + 'is', + 'an', + 'array' + ], + array( + 'this', + 'is', + 'an', + 'array' + ), + array( + 'this', + 'is', + 'an', + 'array' + ), + function($x) + { + echo 'wee'; + + return trim($x); + } +); + +function foo() +{ + myFunction( + 'string'. + // comment + // comment + 'string'. + /* comment + * comment + */ + 'string' + ); +} + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test(); +test(); +test(); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +?> + + + +
  • + log(// ... + 'error', + sprintf( + 'Message: %s', + isset($e->getData()['object']['evidence_details']) + ? $e->getData()['object']['evidence_details']['due_by'] + : '' + ), + array($e->getData()['object']) +); + +?> +
    + $class + ] + ); ?> +
    + + function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +array_filter( + [1, 2], + function ($i) : bool { + return $i === 0; + } +); + +foo( + array( + 'callback' => function () { + $foo = 'foo'; + return; + }, + ) +); + +foo( + $a, + /* + $c, + + $d, + */ + $e +); + +test( + 1,2,3,4 +); + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a','b', 'c' + ); + } +} + +$x = $var( + 'y', + 'x' +); + +$obj->{$x}( + 1, + 2 +); + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)( + 'c', + 'd' +); + +class Foo +{ + public function bar($a, $b) + { + if (!$a || !$b) { + return; + } + + (new stdClass())->a = $a; + } +} + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})('a','b')('c','d'); + +function foo() +{ + Bar( + function () { + } + ); +} + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 7 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 9 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +printf( + '', + $obj->getName(), // Trailing comment. + $obj->getID(), // phpcs:ignore Standard.Category.SniffName -- for reasons. + $option +); + +// Handling of PHP 7.3 trailing comma's. +functionCall($args, $foo,); +functionCall( + $args, + $foo, +); +functionCall( + $args, + $foo, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +$this->foo( + ['a','b'], + true +); + +$this->foo( + // Comment + ['a','b'], + true +); + +function m() +{ + $t = ' + ' . (empty(true) ? ' + ' . f( + '1', + '2', + ) . ' + ' : ''); +} + +class C +{ + + public function m() + { + $a = []; + $t = + "SELECT * FROM t +WHERE f IN(" . implode( + ",", + $a + ) . ")"; + } +} + +$notices = array( + 'index' => sprintf( + translation_function('a text string with %s placeholder'), + 'replacement' + ), +); + +$componentType = $this->componentTypeRepository->findByType($this->identifier) ?: + $this->componentTypeFactory->createForType( + $this->identifier, + $this->className, + true, + $this->isPrototypal + ); + +return [ + 'export-path' => 'exports/database/' + . env( + 'APP_CUSTOMER', + 'not-configured' + ) + . '/' . env( + 'APP_IDENTIFIER', + 'not-configured' + ), +]; + +$methods .= + str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate + ) + . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + +$rangeValues['min'] = + $this->adjustLowerThreshold( + $this->normalizeRatingForFilter($rangeValues['min']) + ); + +$salesOrderThresholdTransfer->fromArray($salesOrderThresholdEntity->toArray(), true) + ->setSalesOrderThresholdValue( + $this->mapSalesOrderThresholdValueTransfer($salesOrderThresholdTransfer, $salesOrderThresholdEntity) + )->setCurrency( + (new CurrencyTransfer())->fromArray($salesOrderThresholdEntity->getCurrency()->toArray(), true) + )->setStore( + (new StoreTransfer())->fromArray($salesOrderThresholdEntity->getStore()->toArray(), true) + ); + +return trim( + preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + ) +); + +$a = ['a' => function ($b) { return $b; }]; +$a['a'](1); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( + 1, + 12, + ), value: true, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js new file mode 100644 index 000000000..5e77e57a2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js @@ -0,0 +1,80 @@ +test( +); +test(); +test(arg, arg2); +test (); +test( ); +test() ; +test( arg); +test( arg ); +test ( arg ); + +if (foo(arg) === true) { + +} + +var something = get(arg1, arg2); +var something = get(arg1, arg2) ; +var something = get(arg1, arg2) ; + +make_foo(string/*the string*/, true/*test*/); +make_foo(string/*the string*/, true/*test*/ ); +make_foo(string /*the string*/, true /*test*/); +make_foo(/*the string*/string, /*test*/true); +make_foo( /*the string*/string, /*test*/true); + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test(arg, arg2); +test( arg, arg2 ); +test( arg, arg2 ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +this.init = function(data) { + a.b('').a(function(itemid, target) { + b( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + }, + '', + function() { + var _showAspectItems = function(itemid) { + a.a(a.c(''), ''); + a.b(a.c('-' + itemid), ''); + }; + a.foo(function(itemid, target) { + _foo(itemid); + }); + } + ); + }); +}; + +a.prototype = { + + a: function() + { + this.addItem( + { + /** + * @return void + */ + a: function() + { + + }, + /** + * @return void + */ + a: function() + { + + }, + } + ); + } +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed new file mode 100644 index 000000000..7855ac677 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed @@ -0,0 +1,84 @@ +test( +); +test(); +test(arg, arg2); +test(); +test(); +test(); +test(arg); +test(arg); +test(arg); + +if (foo(arg) === true) { + +} + +var something = get(arg1, arg2); +var something = get(arg1, arg2); +var something = get(arg1, arg2); + +make_foo(string/*the string*/, true/*test*/); +make_foo(string/*the string*/, true/*test*/); +make_foo(string /*the string*/, true /*test*/); +make_foo(/*the string*/string, /*test*/true); +make_foo(/*the string*/string, /*test*/true); + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test( arg, arg2 ); +test( arg, arg2 ); +test( arg, arg2 ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +this.init = function(data) { + a.b('').a( + function(itemid, target) { + b( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + }, + '', + function() { + var _showAspectItems = function(itemid) { + a.a(a.c(''), ''); + a.b(a.c('-' + itemid), ''); + }; + a.foo( + function(itemid, target) { + _foo(itemid); + } + ); + } + ); + } + ); +}; + +a.prototype = { + + a: function() + { + this.addItem( + { + /** + * @return void + */ + a: function() + { + + }, + /** + * @return void + */ + a: function() + { + + }, + } + ); + } +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php new file mode 100644 index 000000000..1dd59188f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php @@ -0,0 +1,154 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCallSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionCallSignatureUnitTest.inc') + { + if ($testFile === 'FunctionCallSignatureUnitTest.js') { + return [ + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 9 => 2, + 10 => 3, + 17 => 1, + 18 => 1, + 21 => 1, + 24 => 1, + 28 => 2, + 30 => 2, + 35 => 1, + 49 => 1, + 51 => 1, + 54 => 1, + 70 => 1, + 71 => 1, + ]; + }//end if + + return [ + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 9 => 2, + 10 => 3, + 17 => 1, + 18 => 1, + 31 => 1, + 34 => 1, + 43 => 2, + 57 => 1, + 59 => 1, + 63 => 1, + 64 => 1, + 82 => 1, + 93 => 1, + 100 => 1, + 106 => 2, + 119 => 1, + 120 => 1, + 129 => 1, + 137 => 1, + 142 => 2, + 171 => 1, + 180 => 1, + 181 => 1, + 194 => 1, + 213 => 2, + 215 => 2, + 217 => 2, + 218 => 2, + 277 => 1, + 278 => 1, + 303 => 1, + 308 => 1, + 321 => 1, + 322 => 1, + 329 => 1, + 330 => 1, + 337 => 1, + 342 => 1, + 343 => 1, + 345 => 1, + 346 => 2, + 353 => 1, + 354 => 1, + 355 => 2, + 377 => 1, + 378 => 1, + 379 => 1, + 380 => 1, + 385 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 393 => 1, + 394 => 1, + 395 => 1, + 396 => 1, + 411 => 1, + 422 => 1, + 424 => 1, + 429 => 1, + 432 => 1, + 440 => 1, + 441 => 1, + 442 => 1, + 464 => 1, + 510 => 1, + 513 => 1, + 514 => 1, + 523 => 1, + 524 => 3, + 527 => 2, + 539 => 1, + 540 => 1, + 546 => 1, + 547 => 1, + 548 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc new file mode 100644 index 000000000..02e0a20db --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc @@ -0,0 +1,420 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionDeclarationUnitTest.inc') + { + if ($testFile === 'FunctionDeclarationUnitTest.inc') { + $errors = [ + 3 => 1, + 4 => 1, + 5 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 17 => 1, + 44 => 1, + 52 => 1, + 61 => 2, + 98 => 1, + 110 => 2, + 120 => 3, + 121 => 1, + 140 => 1, + 145 => 1, + 161 => 2, + 162 => 2, + 164 => 2, + 167 => 2, + 171 => 1, + 173 => 1, + 201 => 1, + 206 => 1, + 208 => 1, + 216 => 1, + 223 => 1, + 230 => 1, + 237 => 1, + 243 => 1, + 247 => 1, + 251 => 2, + 253 => 2, + 257 => 2, + 259 => 1, + 263 => 1, + 265 => 1, + 269 => 1, + 273 => 1, + 277 => 1, + 278 => 1, + 283 => 1, + 287 => 2, + 289 => 2, + 293 => 2, + 295 => 1, + 299 => 1, + 301 => 1, + 305 => 1, + 309 => 1, + 313 => 1, + 314 => 1, + 350 => 1, + 351 => 1, + 352 => 1, + 353 => 1, + 361 => 1, + 362 => 1, + 363 => 1, + 364 => 1, + 365 => 1, + 366 => 1, + 367 => 1, + 368 => 1, + 369 => 1, + 370 => 1, + 371 => 1, + 402 => 1, + 406 => 1, + ]; + } else { + $errors = [ + 3 => 1, + 4 => 1, + 5 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 17 => 1, + 41 => 1, + 48 => 1, + ]; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc new file mode 100644 index 000000000..8f8d64ab7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.inc @@ -0,0 +1,119 @@ + $a[] = $b; + +class OnlyConstructorPropertyPromotion { + public function __construct( + public string $name = '', + protected $bar + ) {} +} + +class ConstructorPropertyPromotionMixedWithNormalParams { + public function __construct( + public string $name = '', + ?int $optionalParam = 0, + mixed $requiredParam, + ) {} +} + +// Intentional syntax error. Must be last thing in the file. +function diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php new file mode 100644 index 000000000..60d261cbb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidDefaultValueUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 29 => 1, + 34 => 1, + 39 => 1, + 71 => 1, + 76 => 1, + 81 => 1, + 91 => 1, + 99 => 1, + 101 => 1, + 106 => 1, + 114 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc new file mode 100644 index 000000000..053a4fee2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidClassNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 7 => 2, + 9 => 1, + 19 => 1, + 24 => 1, + 26 => 2, + 28 => 1, + 38 => 1, + 40 => 2, + 42 => 2, + 44 => 1, + 46 => 1, + 50 => 1, + 52 => 2, + 54 => 1, + 64 => 1, + 66 => 2, + 68 => 1, + 72 => 1, + 74 => 2, + 76 => 1, + 86 => 1, + 88 => 2, + 90 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc new file mode 100644 index 000000000..18b1a4817 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -0,0 +1,243 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidFunctionNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 2, + 18 => 2, + 19 => 2, + 20 => 2, + 24 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 2, + 31 => 2, + 32 => 2, + 33 => 2, + 35 => 1, + 36 => 1, + 37 => 2, + 38 => 2, + 39 => 2, + 40 => 2, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 73 => 2, + 74 => 2, + 75 => 2, + 76 => 2, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 86 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + 95 => 1, + 96 => 1, + 97 => 1, + 98 => 1, + 99 => 1, + 100 => 1, + 101 => 2, + 102 => 2, + 103 => 2, + 104 => 2, + 123 => 1, + 125 => 1, + 126 => 2, + 129 => 1, + 130 => 1, + 131 => 1, + 132 => 1, + 133 => 1, + 134 => 1, + 135 => 1, + 136 => 1, + 137 => 1, + 138 => 1, + 139 => 1, + 140 => 3, + 141 => 1, + 143 => 1, + 144 => 1, + 145 => 3, + 147 => 2, + 148 => 1, + 149 => 1, + 181 => 1, + 201 => 1, + 203 => 1, + 204 => 2, + 207 => 2, + 212 => 1, + 213 => 1, + 214 => 1, + 235 => 1, + 236 => 2, + 239 => 1, + 242 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 000000000..3c03da3fd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,101 @@ +def["POP_{$cc}_A"]}' + and POP_{$cc}_B = +'{$this->def["POP_{$cc}_B"]}')"; + } +} + +class mpgResponse{ + var $term_id; + var $currentTag; + function characterHandler($parser,$data){ + switch($this->currentTag) + { + case "term_id": { + $this->term_id=$data; + break; + } + } + }//end characterHandler +}//end class mpgResponse + +class foo +{ + const bar = <<setLogger( + new class { + private $varName = 'hello'; + private $_varName = 'hello'; +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 000000000..834852c33 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 17 => 1, + 22 => 1, + 92 => 1, + 93 => 1, + 94 => 1, + 99 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc new file mode 100644 index 000000000..b1b09d932 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc @@ -0,0 +1,142 @@ +someFunction("some", "parameter") +->someOtherFunc(23, 42)-> + someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ->andAThirdFunction(); + + $someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +func( + $bar->foo() +) + ->bar(); + +func( + $bar->foo() +) + ->bar( + $bar->foo() + ->bar() + ->func() + ); + +$object + ->setBar($foo) + ->setFoo($bar); + +if ($bar) { + $object + ->setBar($foo) + ->setFoo($bar); +} + +$response -> CompletedTrackDetails -> TrackDetails -> Events; +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$response + -> CompletedTrackDetails +-> TrackDetails + -> Events; + +$var = get_object( + $foo->something() + ->query() +)->two() + ->three(); + +$foo->one( + $foo + ->two() +); + +get_object()->one() + ->two() + ->three(); + +someclass::one() + ->two() + ->three(); + +(new someclass())->one() + ->two() + ->three(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true + +$someObject + ->startSomething() + ->someOtherFunc(23, 42) +->endSomething() +->doSomething(23, 42) +->endEverything(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() +->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") +->someOtherFunc(23, 42)?-> + someOtherFunc2($one, $two) + +->someOtherFunc3(23, 42) + ?->andAThirdFunction(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") +->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + +->someOtherFunc3(23, 42) + ?->andAThirdFunction(); +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$someObject + ->startSomething(paramName: $value) + ->someOtherFunc(nameA: 23, nameB: 42) +->endSomething($value, name: $value) +->endEverything(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed new file mode 100644 index 000000000..5d5b77bef --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed @@ -0,0 +1,142 @@ +someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ->andAThirdFunction(); + + $someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +func( + $bar->foo() +) + ->bar(); + +func( + $bar->foo() +) + ->bar( + $bar->foo() + ->bar() + ->func() + ); + +$object + ->setBar($foo) + ->setFoo($bar); + +if ($bar) { + $object + ->setBar($foo) + ->setFoo($bar); +} + +$response -> CompletedTrackDetails -> TrackDetails -> Events; +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$var = get_object( + $foo->something() + ->query() +)->two() + ->three(); + +$foo->one( + $foo + ->two() +); + +get_object()->one() + ->two() + ->three(); + +someclass::one() + ->two() + ->three(); + +(new someclass())->one() + ->two() + ->three(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true + +$someObject + ->startSomething() + ->someOtherFunc(23, 42) + ->endSomething() + ->doSomething(23, 42) + ->endEverything(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ?->andAThirdFunction(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ?->andAThirdFunction(); +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$someObject + ->startSomething(paramName: $value) + ->someOtherFunc(nameA: 23, nameB: 42) + ->endSomething($value, name: $value) + ->endEverything(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php new file mode 100644 index 000000000..0cad3efc1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php @@ -0,0 +1,74 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectOperatorIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 2, + 6 => 1, + 15 => 1, + 27 => 1, + 37 => 1, + 38 => 1, + 48 => 1, + 49 => 1, + 50 => 1, + 65 => 1, + 69 => 1, + 73 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 95 => 1, + 103 => 1, + 119 => 2, + 122 => 1, + 131 => 1, + 134 => 1, + 140 => 1, + 141 => 1, + 142 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc new file mode 100644 index 000000000..3f9006792 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc @@ -0,0 +1,164 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +switch ($foo) { +case 1: + switch ($bar) { + default: + if ($something) { + echo $string{1}; + } else if ($else) { + switch ($else) { + case 1: + // Do something. + break; + default: + // Do something. + break; + } + } + } +break; +case 2: + // Do something; + break; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + default: + return 'Unknown'; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + return 'Processing.'; + default: + return 'Unknown'; +} + +switch($i) { +case 1: {} +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + exit; + default: + exit; +} + +if ($foo): + if ($bar): + $foo = 1; + elseif ($baz): + $foo = 2; + endif; +endif; + +if ($foo): +elseif ($baz): $foo = 2; +endif; + +?> +
      + +
    • + +
    +
      + +
    • + +
    +
      + +
    • + +
    + +getSummaryCount(); ?> +
    class="empty"> + + 'a', 2 => 'b' }; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' + }; + +enum Enum +{ +} + +enum Suits {} + +enum Cards +{ + } diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed new file mode 100644 index 000000000..f369c2b2f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed @@ -0,0 +1,170 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +switch ($foo) { +case 1: + switch ($bar) { + default: + if ($something) { + echo $string{1}; + } else if ($else) { + switch ($else) { + case 1: + // Do something. + break; + default: + // Do something. + break; + } + } + } + break; +case 2: + // Do something; + break; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + default: + return 'Unknown'; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + return 'Processing.'; + default: + return 'Unknown'; +} + +switch($i) { +case 1: { + } +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + exit; + default: + exit; +} + +if ($foo): + if ($bar): + $foo = 1; + elseif ($baz): + $foo = 2; + endif; +endif; + +if ($foo): +elseif ($baz): $foo = 2; +endif; + +?> +
      + +
    • + +
    +
      + +
    • + +
    +
      + +
    • + +
    + +getSummaryCount(); ?> +
    class="empty"> + + 'a', 2 => 'b' +}; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' +}; + +enum Enum +{ +} + +enum Suits { +} + +enum Cards +{ +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php new file mode 100644 index 000000000..265932549 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 13 => 1, + 24 => 1, + 30 => 1, + 61 => 1, + 65 => 1, + 85 => 1, + 89 => 1, + 98 => 1, + 122 => 1, + 127 => 1, + 135 => 1, + 141 => 1, + 146 => 1, + 149 => 1, + 154 => 1, + 160 => 1, + 164 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc new file mode 100644 index 000000000..b122a1476 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc @@ -0,0 +1,314 @@ +hello(); // error here + } + + function hello() // error here + { // no error here as brackets can be put anywhere in the pear standard + echo 'hello'; + } + + function hello2() + { + if (TRUE) { // error here + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; // error here + } + + while (TRUE) { + echo 'hello'; // error here + } + + do { // error here + echo 'hello'; // error here + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* + * + * + * + */ + + /** + */ + + /* + This comment has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 10 => 1, + 17 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 58 => 1, + 123 => 1, + 224 => 1, + 225 => 1, + 279 => 1, + 284 => 1, + 311 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml new file mode 100644 index 000000000..1bf94ca54 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml @@ -0,0 +1,41 @@ + + + The PEAR coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 000000000..eaae99b22 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,48 @@ + + + + + + + class Bar { +} + ]]> + + + class Bar { +} + +class Baz { +} + ]]> + + + + + namespace Foo; + +class Bar { +} + ]]> + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml new file mode 100644 index 000000000..0ed04a07d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml @@ -0,0 +1,27 @@ + + + + + + + + + + echo "Class Foo loaded." + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml new file mode 100644 index 000000000..8db899d67 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + doBar() + { + } +} + ]]> + + + do_bar() + { + } +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..3db26f6fd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in + * the token stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $errorData = [strtolower($tokens[$stackPtr]['content'])]; + + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], ($tokens[$stackPtr]['scope_closer'] + 1)); + if ($nextClass !== false) { + $error = 'Each %s must be in a file by itself'; + $phpcsFile->addError($error, $nextClass, 'MultipleClasses', $errorData); + $phpcsFile->recordMetric($stackPtr, 'One class per file', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes'); + } + + $namespace = $phpcsFile->findNext([T_NAMESPACE, T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], 0); + if ($tokens[$namespace]['code'] !== T_NAMESPACE) { + $error = 'Each %s must be in a namespace of at least one level (a top-level vendor name)'; + $phpcsFile->addError($error, $stackPtr, 'MissingNamespace', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'yes'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php new file mode 100644 index 000000000..3f8c5e0d5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php @@ -0,0 +1,299 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SideEffectsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the token stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $result = $this->searchForConflict($phpcsFile, 0, ($phpcsFile->numTokens - 1), $tokens); + + if ($result['symbol'] !== null && $result['effect'] !== null) { + $error = 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line %s and the first side effect is on line %s.'; + $data = [ + $tokens[$result['symbol']]['line'], + $tokens[$result['effect']]['line'], + ]; + $phpcsFile->addWarning($error, 0, 'FoundWithSymbols', $data); + $phpcsFile->recordMetric($stackPtr, 'Declarations and side effects mixed', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Declarations and side effects mixed', 'no'); + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + + /** + * Searches for symbol declarations and side effects. + * + * Returns the positions of both the first symbol declared and the first + * side effect in the file. A NULL value for either indicates nothing was + * found. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $start The token to start searching from. + * @param int $end The token to search to. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return array + */ + private function searchForConflict($phpcsFile, $start, $end, $tokens) + { + $symbols = [ + T_CLASS => T_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + T_FUNCTION => T_FUNCTION, + ]; + + $conditions = [ + T_IF => T_IF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ]; + + $checkAnnotations = $phpcsFile->config->annotations; + + $firstSymbol = null; + $firstEffect = null; + for ($i = $start; $i <= $end; $i++) { + // Respect phpcs:disable comments. + if ($checkAnnotations === true + && $tokens[$i]['code'] === T_PHPCS_DISABLE + && (empty($tokens[$i]['sniffCodes']) === true + || isset($tokens[$i]['sniffCodes']['PSR1']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects']) === true) + ) { + do { + $i = $phpcsFile->findNext(T_PHPCS_ENABLE, ($i + 1)); + } while ($i !== false + && empty($tokens[$i]['sniffCodes']) === false + && isset($tokens[$i]['sniffCodes']['PSR1']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects']) === false); + + if ($i === false) { + // The entire rest of the file is disabled, + // so return what we have so far. + break; + } + + continue; + } + + // Ignore whitespace and comments. + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore PHP tags. + if ($tokens[$i]['code'] === T_OPEN_TAG + || $tokens[$i]['code'] === T_CLOSE_TAG + ) { + continue; + } + + // Ignore shebang. + if (substr($tokens[$i]['content'], 0, 2) === '#!') { + continue; + } + + // Ignore logical operators. + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore entire namespace, declare, const and use statements. + if ($tokens[$i]['code'] === T_NAMESPACE + || $tokens[$i]['code'] === T_USE + || $tokens[$i]['code'] === T_DECLARE + || $tokens[$i]['code'] === T_CONST + ) { + if (isset($tokens[$i]['scope_opener']) === true) { + $i = $tokens[$i]['scope_closer']; + if ($tokens[$i]['code'] === T_ENDDECLARE) { + $semicolon = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($semicolon !== false && $tokens[$semicolon]['code'] === T_SEMICOLON) { + $i = $semicolon; + } + } + } else { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1)); + if ($semicolon !== false) { + $i = $semicolon; + } + } + + continue; + } + + // Ignore function/class prefixes. + if (isset(Tokens::$methodPrefixes[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore anon classes. + if ($tokens[$i]['code'] === T_ANON_CLASS) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + // Ignore attributes. + if ($tokens[$i]['code'] === T_ATTRIBUTE + && isset($tokens[$i]['attribute_closer']) === true + ) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + // Detect and skip over symbols. + if (isset($symbols[$tokens[$i]['code']]) === true + && isset($tokens[$i]['scope_closer']) === true + ) { + if ($firstSymbol === null) { + $firstSymbol = $i; + } + + $i = $tokens[$i]['scope_closer']; + continue; + } else if ($tokens[$i]['code'] === T_STRING + && strtolower($tokens[$i]['content']) === 'define' + ) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_NULLSAFE_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_DOUBLE_COLON + && $tokens[$prev]['code'] !== T_FUNCTION + ) { + if ($firstSymbol === null) { + $firstSymbol = $i; + } + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1)); + if ($semicolon !== false) { + $i = $semicolon; + } + + continue; + } + }//end if + + // Special case for defined() as it can be used to see + // if a constant (a symbol) should be defined or not and + // doesn't need to use a full conditional block. + if ($tokens[$i]['code'] === T_STRING + && strtolower($tokens[$i]['content']) === 'defined' + ) { + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($openBracket !== false + && $tokens[$openBracket]['code'] === T_OPEN_PARENTHESIS + && isset($tokens[$openBracket]['parenthesis_closer']) === true + ) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_NULLSAFE_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_DOUBLE_COLON + && $tokens[$prev]['code'] !== T_FUNCTION + ) { + $i = $tokens[$openBracket]['parenthesis_closer']; + continue; + } + } + }//end if + + // Conditional statements are allowed in symbol files as long as the + // contents is only a symbol definition. So don't count these as effects + // in this case. + if (isset($conditions[$tokens[$i]['code']]) === true) { + if (isset($tokens[$i]['scope_opener']) === false) { + // Probably an "else if", so just ignore. + continue; + } + + $result = $this->searchForConflict( + $phpcsFile, + ($tokens[$i]['scope_opener'] + 1), + ($tokens[$i]['scope_closer'] - 1), + $tokens + ); + + if ($result['symbol'] !== null) { + if ($firstSymbol === null) { + $firstSymbol = $result['symbol']; + } + + if ($result['effect'] !== null) { + // Found a conflict. + $firstEffect = $result['effect']; + break; + } + } + + if ($firstEffect === null) { + $firstEffect = $result['effect']; + } + + $i = $tokens[$i]['scope_closer']; + continue; + }//end if + + if ($firstEffect === null) { + $firstEffect = $i; + } + + if ($firstSymbol !== null) { + // We have a conflict we have to report, so no point continuing. + break; + } + }//end for + + return [ + 'symbol' => $firstSymbol, + 'effect' => $firstEffect, + ]; + + }//end searchForConflict() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php new file mode 100644 index 000000000..2d1381462 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff as GenericCamelCapsFunctionNameSniff; +use PHP_CodeSniffer\Util\Common; + +class CamelCapsMethodNameSniff extends GenericCamelCapsFunctionNameSniff +{ + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + // Ignore magic methods. + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = strtolower(substr($methodName, 2)); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + } + + $testName = ltrim($methodName, '_'); + if ($testName !== '' && Common::isCamelCaps($testName, false, true, false) === false) { + $error = 'Method name "%s" is not in camel caps format'; + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc new file mode 100644 index 000000000..58cb85e39 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile === 'ClassDeclarationUnitTest.2.inc') { + return []; + } + + return [ + 2 => 1, + 3 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc new file mode 100644 index 000000000..ca538823c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc @@ -0,0 +1,79 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc new file mode 100644 index 000000000..63f256d4e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc @@ -0,0 +1,8 @@ +define("MAXSIZE", 100); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc new file mode 100644 index 000000000..9499885b6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc @@ -0,0 +1,2 @@ +define("MAXSIZE", 100); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc new file mode 100644 index 000000000..0500d10e6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc @@ -0,0 +1,2 @@ +defined('MINSIZE') or define("MAXSIZE", 100); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc new file mode 100644 index 000000000..588ece584 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc @@ -0,0 +1,2 @@ +defined('MINSIZE') or define("MAXSIZE", 100); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc new file mode 100644 index 000000000..4c9b8e669 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc @@ -0,0 +1,24 @@ +define(); +echo $object -> define(); +Foo::define(); + +$c = new class extends Something{ + + public function someMethod() + { + // ... + } + +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc new file mode 100644 index 000000000..d4ae77eed --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc @@ -0,0 +1,6 @@ + +'; +} + +printHead(); +?> + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc new file mode 100644 index 000000000..7265c6377 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc @@ -0,0 +1,2 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc new file mode 100644 index 000000000..e02fed4b0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SideEffectsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Set CLI values before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'SideEffectsUnitTest.12.inc') { + $config->annotations = false; + } + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'SideEffectsUnitTest.3.inc': + case 'SideEffectsUnitTest.4.inc': + case 'SideEffectsUnitTest.5.inc': + case 'SideEffectsUnitTest.10.inc': + case 'SideEffectsUnitTest.12.inc': + case 'SideEffectsUnitTest.15.inc': + case 'SideEffectsUnitTest.16.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc new file mode 100644 index 000000000..7381517f0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CamelCapsMethodNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 17 => 1, + 21 => 1, + 25 => 1, + 26 => 1, + 77 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml new file mode 100644 index 000000000..65cbe20e9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml @@ -0,0 +1,47 @@ + + + The PSR1 coding standard. + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml new file mode 100644 index 000000000..ae24611d0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml new file mode 100644 index 000000000..2032c9a62 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml new file mode 100644 index 000000000..9bb5a8a55 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + (boolean) $isValid; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml new file mode 100644 index 000000000..b74e8b429 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml @@ -0,0 +1,28 @@ + + + + + + + + + + SubnamespaceOne\AnotherNamespace\ClassA, + SubnamespaceOne\ClassB, + ClassZ, +}; + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml new file mode 100644 index 000000000..981b1d97a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml @@ -0,0 +1,27 @@ + + + + + + + $b) { + $variable = $foo ? 'foo' : 'bar'; +} + ]]> + + + $b) { + $variable=$foo?'foo':'bar'; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php new file mode 100644 index 000000000..7a33bd947 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php @@ -0,0 +1,242 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\FunctionCallArgumentSpacingSniff; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff; +use PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\MultiLineFunctionDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class AnonClassDeclarationSniff extends ClassDeclarationSniff +{ + + /** + * The PSR2 MultiLineFunctionDeclarations sniff. + * + * @var MultiLineFunctionDeclarationSniff + */ + private $multiLineSniff = null; + + /** + * The Generic FunctionCallArgumentSpacing sniff. + * + * @var FunctionCallArgumentSpacingSniff + */ + private $functionCallSniff = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ANON_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $this->multiLineSniff = new MultiLineFunctionDeclarationSniff(); + $this->functionCallSniff = new FunctionCallArgumentSpacingSniff(); + + $this->processOpen($phpcsFile, $stackPtr); + $this->processClose($phpcsFile, $stackPtr); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) { + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + if ($this->multiLineSniff->isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineArgumentList($phpcsFile, $stackPtr); + } else { + $this->processSingleLineArgumentList($phpcsFile, $stackPtr); + } + + $this->functionCallSniff->checkSpacing($phpcsFile, $stackPtr, $openBracket); + } + + $opener = $tokens[$stackPtr]['scope_opener']; + if ($tokens[$opener]['line'] === $tokens[$stackPtr]['line']) { + return; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $stackPtr, true); + + $implements = $phpcsFile->findPrevious(T_IMPLEMENTS, ($opener - 1), $stackPtr); + if ($implements !== false + && $tokens[$opener]['line'] !== $tokens[$implements]['line'] + && $tokens[$opener]['line'] === $tokens[$prev]['line'] + ) { + // Opening brace must be on a new line as implements list wraps. + $error = 'Opening brace must be on the line after the last implemented interface'; + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceSameLine'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $indent = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($prev + 1), ''); + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->addContentBefore($opener, $indent); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[$opener]['line'] > ($tokens[$prev]['line'] + 1)) { + // Opening brace is on a new line, so there must be no blank line before it. + $error = 'Opening brace must not be preceded by a blank line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($prev + 1); $x < $opener; $x++) { + if ($tokens[$x]['line'] === $tokens[$prev]['line']) { + // Maintain existing newline. + continue; + } + + if ($tokens[$x]['line'] === $tokens[$opener]['line']) { + // Maintain existing indent. + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end process() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processSingleLineArgumentList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($openBracket === ($closeBracket - 1)) { + return; + } + + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $error = 'Space after opening parenthesis of single-line argument list prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + + $spaceBeforeClose = 0; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), $openBracket, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Need a newline after these tokens, so ignore this rule. + return; + } + + if ($tokens[$prev]['line'] !== $tokens[$closeBracket]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closeBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closeBracket - 1)]['length']; + } + + if ($spaceBeforeClose !== 0) { + $error = 'Space before closing parenthesis of single-line argument list prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeCloseBracket'); + if ($fix === true) { + if ($spaceBeforeClose === 'newline') { + $phpcsFile->fixer->beginChangeset(); + + $closingContent = ')'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $closingContent .= ';'; + for ($i = ($closeBracket + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // We want to jump over any whitespace or inline comment and + // move the closing parenthesis after any other token. + $prev = ($closeBracket - 1); + while (isset(Tokens::$emptyTokens[$tokens[$prev]['code']]) === true) { + if (($tokens[$prev]['code'] === T_COMMENT) + && (strpos($tokens[$prev]['content'], '*/') !== false) + ) { + break; + } + + $prev--; + } + + $phpcsFile->fixer->addContent($prev, $closingContent); + + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + for ($i = ($prevNonWhitespace + 1); $i <= $closeBracket; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket - 1), ''); + }//end if + }//end if + }//end if + + }//end processSingleLineArgumentList() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processMultiLineArgumentList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + + $this->multiLineSniff->processBracket($phpcsFile, $openBracket, $tokens, 'argument'); + $this->multiLineSniff->processArgumentList($phpcsFile, $stackPtr, $this->indent, 'argument'); + + }//end processMultiLineArgumentList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php new file mode 100644 index 000000000..e4ebd576a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassInstantiationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the class name. + $allowed = [ + T_STRING => T_STRING, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_VARIABLE => T_VARIABLE, + T_DOLLAR => T_DOLLAR, + T_OBJECT_OPERATOR => T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR => T_NULLSAFE_OBJECT_OPERATOR, + T_DOUBLE_COLON => T_DOUBLE_COLON, + ]; + + $allowed += Tokens::$emptyTokens; + + $classNameEnd = null; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if (isset($allowed[$tokens[$i]['code']]) === true) { + continue; + } + + // Skip over potential attributes for anonymous classes. + if ($tokens[$i]['code'] === T_ATTRIBUTE + && isset($tokens[$i]['attribute_closer']) === true + ) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + ) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + $classNameEnd = $i; + break; + }//end for + + if ($classNameEnd === null) { + return; + } + + if ($tokens[$classNameEnd]['code'] === T_ANON_CLASS) { + // Ignore anon classes. + return; + } + + if ($tokens[$classNameEnd]['code'] === T_OPEN_PARENTHESIS) { + // Using parenthesis. + return; + } + + if ($classNameEnd === $stackPtr) { + // Failed to find the class name. + return; + } + + $error = 'Parentheses must be used when instantiating a new class'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingParentheses'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($classNameEnd - 1), null, true); + $phpcsFile->fixer->addContent($prev, '()'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php new file mode 100644 index 000000000..fa1f8d60e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $closer = $tokens[$stackPtr]['scope_closer']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), null, true); + if ($next === false + || $tokens[$next]['line'] !== $tokens[$closer]['line'] + ) { + return; + } + + $error = 'Closing brace must not be followed by any comment or statement on the same line'; + $phpcsFile->addError($error, $closer, 'StatementAfter'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php new file mode 100644 index 000000000..83ffda4df --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningBraceSpaceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$ooScopeTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['scope_opener']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + if ($next === false + || $tokens[$next]['line'] <= ($tokens[$opener]['line'] + 1) + ) { + return; + } + + $error = 'Opening brace must not be followed by a blank line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'Found'); + if ($fix === false) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php new file mode 100644 index 000000000..b87c33918 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php @@ -0,0 +1,229 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class BooleanOperatorPlacementSniff implements Sniff +{ + + /** + * Used to restrict the placement of the boolean operator. + * + * Allowed value are "first" or "last". + * + * @var string|null + */ + public $allowOnly = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_SWITCH, + T_ELSEIF, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) { + // Conditions are all on the same line. + return; + } + + $find = [ + T_BOOLEAN_AND, + T_BOOLEAN_OR, + ]; + + if ($this->allowOnly === 'first' || $this->allowOnly === 'last') { + $position = $this->allowOnly; + } else { + $position = null; + } + + $operator = $parenOpener; + $error = false; + $operators = []; + + do { + $operator = $phpcsFile->findNext($find, ($operator + 1), $parenCloser); + if ($operator === false) { + break; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); + if ($prev === false) { + // Parse error. + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + if ($next === false) { + // Parse error. + return; + } + + $firstOnLine = false; + $lastOnLine = false; + + if ($tokens[$prev]['line'] < $tokens[$operator]['line']) { + // The boolean operator is the first content on the line. + $firstOnLine = true; + } + + if ($tokens[$next]['line'] > $tokens[$operator]['line']) { + // The boolean operator is the last content on the line. + $lastOnLine = true; + } + + if ($firstOnLine === true && $lastOnLine === true) { + // The operator is the only content on the line. + // Don't record it because we can't determine + // placement information from looking at it. + continue; + } + + $operators[] = $operator; + + if ($firstOnLine === false && $lastOnLine === false) { + // It's in the middle of content, so we can't determine + // placement information from looking at it, but we may + // still need to process it. + continue; + } + + if ($firstOnLine === true) { + if ($position === null) { + $position = 'first'; + } + + if ($position !== 'first') { + $error = true; + } + } else { + if ($position === null) { + $position = 'last'; + } + + if ($position !== 'last') { + $error = true; + } + } + } while ($operator !== false); + + if ($error === false) { + return; + } + + switch ($this->allowOnly) { + case 'first': + $error = 'Boolean operators between conditions must be at the beginning of the line'; + break; + case 'last': + $error = 'Boolean operators between conditions must be at the end of the line'; + break; + default: + $error = 'Boolean operators between conditions must be at the beginning or end of the line, but not both'; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundMixed'); + if ($fix === false) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + foreach ($operators as $operator) { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + + if ($position === 'last') { + if ($tokens[$next]['line'] === $tokens[$operator]['line']) { + if ($tokens[$prev]['line'] === $tokens[$operator]['line']) { + // Move the content after the operator to the next line. + if ($tokens[($operator + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator + 1), ''); + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $operator, true); + $padding = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->addContent($operator, $phpcsFile->eolChar.$padding); + } else { + // Move the operator to the end of the previous line. + if ($tokens[($operator + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator + 1), ''); + } + + $phpcsFile->fixer->addContent($prev, ' '.$tokens[$operator]['content']); + $phpcsFile->fixer->replaceToken($operator, ''); + } + }//end if + } else { + if ($tokens[$prev]['line'] === $tokens[$operator]['line']) { + if ($tokens[$next]['line'] === $tokens[$operator]['line']) { + // Move the operator, and the rest of the expression, to the next line. + if ($tokens[($operator - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator - 1), ''); + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $operator, true); + $padding = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->addContentBefore($operator, $phpcsFile->eolChar.$padding); + } else { + // Move the operator to the start of the next line. + if ($tokens[($operator - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator - 1), ''); + } + + $phpcsFile->fixer->addContentBefore($next, $tokens[$operator]['content'].' '); + $phpcsFile->fixer->replaceToken($operator, ''); + } + }//end if + }//end if + }//end foreach + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..3d29c4ace --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php @@ -0,0 +1,192 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ControlStructureSpacingSniff as PSR2Spacing; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_ELSE, + T_ELSEIF, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) { + // Conditions are all on the same line, so follow PSR2. + $sniff = new PSR2Spacing(); + return $sniff->process($phpcsFile, $stackPtr); + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($parenOpener + 1), $parenCloser, true); + if ($next === false) { + // No conditions; parse error. + return; + } + + // Check the first expression. + if ($tokens[$next]['line'] !== ($tokens[$parenOpener]['line'] + 1)) { + $error = 'The first expression of a multi-line control structure must be on the line after the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, $next, 'FirstExpressionLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($parenOpener); + } + } + + // Check the indent of each line. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $requiredIndent = ($tokens[$first]['column'] + $this->indent - 1); + for ($i = $parenOpener; $i < $parenCloser; $i++) { + if ($tokens[$i]['column'] !== 1 + || $tokens[($i + 1)]['line'] > $tokens[$i]['line'] + || isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true + ) { + continue; + } + + if (($i + 1) === $parenCloser) { + break; + } + + // Leave indentation inside multi-line strings. + if (isset(Tokens::$textStringTokens[$tokens[$i]['code']]) === true + || isset(Tokens::$heredocTokens[$tokens[$i]['code']]) === true + ) { + continue; + } + + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundIndent = 0; + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($foundIndent < $requiredIndent) { + $error = 'Each line in a multi-line control structure must be indented at least once; expected at least %s spaces, but found %s'; + $data = [ + $requiredIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'LineIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $padding); + } else { + $phpcsFile->fixer->replaceToken($i, $padding); + } + } + } + }//end for + + // Check the closing parenthesis. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($parenCloser - 1), $parenOpener, true); + if ($tokens[$parenCloser]['line'] !== ($tokens[$prev]['line'] + 1)) { + $error = 'The closing parenthesis of a multi-line control structure must be on the line after the last expression'; + $fix = $phpcsFile->addFixableError($error, $parenCloser, 'CloseParenthesisLine'); + if ($fix === true) { + if ($tokens[$parenCloser]['line'] === $tokens[$prev]['line']) { + $phpcsFile->fixer->addNewlineBefore($parenCloser); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $parenCloser; $i++) { + // Maintain existing newline. + if ($tokens[$i]['line'] === $tokens[$prev]['line']) { + continue; + } + + // Maintain existing indent. + if ($tokens[$i]['line'] === $tokens[$parenCloser]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[$parenCloser]['line'] !== $tokens[$prev]['line']) { + $requiredIndent = ($tokens[$first]['column'] - 1); + $foundIndent = ($tokens[$parenCloser]['column'] - 1); + if ($foundIndent !== $requiredIndent) { + $error = 'The closing parenthesis of a multi-line control structure must be indented to the same level as start of the control structure; expected %s spaces but found %s'; + $data = [ + $requiredIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $parenCloser, 'CloseParenthesisIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($parenCloser, $padding); + } else { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), $padding); + } + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php new file mode 100644 index 000000000..67776c33d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php @@ -0,0 +1,256 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DeclareStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DECLARE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + + // There should be no space between declare keyword and opening parenthesis. + $parenthesis = ($stackPtr + 1); + if ($tokens[($stackPtr + 1)]['type'] !== 'T_OPEN_PARENTHESIS') { + $parenthesis = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $error = 'Expected no space between declare keyword and opening parenthesis in a declare statement'; + + if ($tokens[$parenthesis]['type'] === 'T_OPEN_PARENTHESIS') { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFoundAfterDeclare'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } else { + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundAfterDeclare'); + $parenthesis = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($parenthesis + 1)); + } + } + + // There should be no space between open parenthesis and the directive. + $string = $phpcsFile->findNext(T_WHITESPACE, ($parenthesis + 1), null, true); + if ($parenthesis !== false) { + if ($tokens[($parenthesis + 1)]['type'] !== 'T_STRING') { + $error = 'Expected no space between opening parenthesis and directive in a declare statement'; + + if ($tokens[$string]['type'] === 'T_STRING') { + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundBeforeDirective'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ''); + } + } else { + $phpcsFile->addError($error, $string, 'SpaceFoundBeforeDirective'); + $string = $phpcsFile->findNext(T_STRING, ($string + 1)); + } + } + } + + // There should be no space between directive and the equal sign. + $equals = $phpcsFile->findNext(T_WHITESPACE, ($string + 1), null, true); + if ($string !== false) { + // The directive must be in lowercase. + if ($tokens[$string]['content'] !== strtolower($tokens[$string]['content'])) { + $error = 'The directive of a declare statement must be in lowercase'; + $fix = $phpcsFile->addFixableError($error, $string, 'DirectiveNotLowercase'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($string, strtolower($tokens[$string]['content'])); + } + } + + if ($tokens[($string + 1)]['type'] !== 'T_EQUAL') { + $error = 'Expected no space between directive and the equals sign in a declare statement'; + + if ($tokens[$equals]['type'] === 'T_EQUAL') { + $fix = $phpcsFile->addFixableError($error, $equals, 'SpaceFoundAfterDirective'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($string + 1), ''); + } + } else { + $phpcsFile->addError($error, $equals, 'SpaceFoundAfterDirective'); + $equals = $phpcsFile->findNext(T_EQUAL, ($equals + 1)); + } + } + }//end if + + // There should be no space between equal sign and directive value. + $value = $phpcsFile->findNext(T_WHITESPACE, ($equals + 1), null, true); + if ($equals !== false) { + if ($tokens[($equals + 1)]['type'] !== 'T_LNUMBER') { + $error = 'Expected no space between equal sign and the directive value in a declare statement'; + + if ($tokens[$value]['type'] === 'T_LNUMBER') { + $fix = $phpcsFile->addFixableError($error, $value, 'SpaceFoundBeforeDirectiveValue'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($equals + 1), ''); + } + } else { + $phpcsFile->addError($error, $value, 'SpaceFoundBeforeDirectiveValue'); + $value = $phpcsFile->findNext(T_LNUMBER, ($value + 1)); + } + } + } + + $parenthesis = $phpcsFile->findNext(T_WHITESPACE, ($value + 1), null, true); + if ($value !== false) { + if ($tokens[($value + 1)]['type'] !== 'T_CLOSE_PARENTHESIS') { + $error = 'Expected no space between the directive value and closing parenthesis in a declare statement'; + + if ($tokens[$parenthesis]['type'] === 'T_CLOSE_PARENTHESIS') { + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundAfterDirectiveValue'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($value + 1), ''); + } + } else { + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundAfterDirectiveValue'); + $parenthesis = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, ($parenthesis + 1)); + } + } + } + + // Check for semicolon. + $curlyBracket = false; + if ($tokens[($parenthesis + 1)]['type'] !== 'T_SEMICOLON') { + $token = $phpcsFile->findNext(T_WHITESPACE, ($parenthesis + 1), null, true); + + if ($tokens[$token]['type'] === 'T_OPEN_CURLY_BRACKET') { + // Block declaration. + $curlyBracket = $token; + } else if ($tokens[$token]['type'] === 'T_SEMICOLON') { + $error = 'Expected no space between the closing parenthesis and the semicolon in a declare statement'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundBeforeSemicolon'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ''); + } + } else if ($tokens[$token]['type'] === 'T_CLOSE_TAG') { + if ($tokens[($parenthesis)]['line'] !== $tokens[$token]['line']) { + // Close tag must be on the same line.. + $error = 'The close tag must be on the same line as the declare statement'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'CloseTagOnNewLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ' '); + } + } + } else { + $error = 'Expected no space between the closing parenthesis and the semicolon in a declare statement'; + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundBeforeSemicolon'); + + // See if there is a semicolon or curly bracket after this token. + $token = $phpcsFile->findNext([T_WHITESPACE, T_COMMENT], ($token + 1), null, true); + if ($tokens[$token]['type'] === 'T_OPEN_CURLY_BRACKET') { + $curlyBracket = $token; + } + }//end if + }//end if + + if ($curlyBracket !== false) { + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBracket - 1), null, true); + $error = 'Expected one space between closing parenthesis and opening curly bracket in a declare statement'; + + // The opening curly bracket must on the same line with a single space between closing bracket. + if ($tokens[$prevToken]['type'] !== 'T_CLOSE_PARENTHESIS') { + $phpcsFile->addError($error, $curlyBracket, 'ExtraSpaceFoundAfterBracket'); + } else if ($phpcsFile->getTokensAsString(($prevToken + 1), ($curlyBracket - $prevToken - 1)) !== ' ') { + $fix = $phpcsFile->addFixableError($error, $curlyBracket, 'ExtraSpaceFoundAfterBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($prevToken + 1), ' '); + $nextToken = ($prevToken + 2); + while ($nextToken !== $curlyBracket) { + $phpcsFile->fixer->replaceToken($nextToken, ''); + $nextToken++; + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $closeCurlyBracket = $tokens[$curlyBracket]['bracket_closer']; + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($closeCurlyBracket - 1), null, true); + $nextToken = $phpcsFile->findNext([T_WHITESPACE, T_COMMENT], ($closeCurlyBracket + 1), null, true); + $line = $tokens[$closeCurlyBracket]['line']; + + // The closing curly bracket must be on a new line. + if ($tokens[$prevToken]['line'] === $line || $tokens[$nextToken]['line'] === $line) { + if ($tokens[$prevToken]['line'] === $line) { + $error = 'The closing curly bracket of a declare statement must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $prevToken, 'CurlyBracketNotOnNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($prevToken); + } + } + }//end if + + // Closing curly bracket must align with the declare keyword. + if ($tokens[$stackPtr]['column'] !== $tokens[$closeCurlyBracket]['column']) { + $error = 'The closing curly bracket of a declare statements must be aligned with the declare keyword'; + + $fix = $phpcsFile->addFixableError($error, $closeCurlyBracket, 'CloseBracketNotAligned'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closeCurlyBracket - 1), str_repeat(' ', ($tokens[$stackPtr]['column'] - 1))); + } + } + + // The open curly bracket must be the last code on the line. + $token = $phpcsFile->findNext(Tokens::$emptyTokens, ($curlyBracket + 1), null, true); + if ($tokens[$curlyBracket]['line'] === $tokens[$token]['line']) { + $error = 'The open curly bracket of a declare statement must be the last code on the line'; + $fix = $phpcsFile->addFixableError($error, $token, 'CodeFoundAfterCurlyBracket'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($token - 1), null, true); + + for ($i = ($prevToken + 1); $i < $token; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewLineBefore($token); + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php new file mode 100644 index 000000000..8a8255cf4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php @@ -0,0 +1,428 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FileHeaderSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return int|null + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $possibleHeaders = []; + + $searchFor = Tokens::$ooScopeTokens; + $searchFor[T_OPEN_TAG] = T_OPEN_TAG; + + $openTag = $stackPtr; + do { + $headerLines = $this->getHeaderLines($phpcsFile, $openTag); + if (empty($headerLines) === true && $openTag === $stackPtr) { + // No content in the file. + return; + } + + $possibleHeaders[$openTag] = $headerLines; + if (count($headerLines) > 1) { + break; + } + + $next = $phpcsFile->findNext($searchFor, ($openTag + 1)); + if (isset(Tokens::$ooScopeTokens[$tokens[$next]['code']]) === true) { + // Once we find an OO token, the file content has + // definitely started. + break; + } + + $openTag = $next; + } while ($openTag !== false); + + if ($openTag === false) { + // We never found a proper file header. + // If the file has multiple PHP open tags, we know + // that it must be a mix of PHP and HTML (or similar) + // so the header rules do not apply. + if (count($possibleHeaders) > 1) { + return $phpcsFile->numTokens; + } + + // There is only one possible header. + // If it is the first content in the file, it technically + // serves as the file header, and the open tag needs to + // have a newline after it. Otherwise, ignore it. + if ($stackPtr > 0) { + return $phpcsFile->numTokens; + } + + $openTag = $stackPtr; + } else if (count($possibleHeaders) > 1) { + // There are other PHP blocks before the file header. + $error = 'The file header must be the first content in the file'; + $phpcsFile->addError($error, $openTag, 'HeaderPosition'); + } else { + // The first possible header was the file header block, + // so make sure it is the first content in the file. + if ($openTag !== 0) { + // Allow for hashbang lines. + $hashbang = false; + if ($tokens[($openTag - 1)]['code'] === T_INLINE_HTML) { + $content = trim($tokens[($openTag - 1)]['content']); + if (substr($content, 0, 2) === '#!') { + $hashbang = true; + } + } + + if ($hashbang === false) { + $error = 'The file header must be the first content in the file'; + $phpcsFile->addError($error, $openTag, 'HeaderPosition'); + } + } + }//end if + + $this->processHeaderLines($phpcsFile, $possibleHeaders[$openTag]); + + return $phpcsFile->numTokens; + + }//end process() + + + /** + * Gather information about the statements inside a possible file header. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return array + */ + public function getHeaderLines(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + return []; + } + + $headerLines = []; + $headerLines[] = [ + 'type' => 'tag', + 'start' => $stackPtr, + 'end' => $stackPtr, + ]; + + $foundDocblock = false; + + $commentOpeners = Tokens::$scopeOpeners; + unset($commentOpeners[T_NAMESPACE]); + unset($commentOpeners[T_DECLARE]); + unset($commentOpeners[T_USE]); + unset($commentOpeners[T_IF]); + unset($commentOpeners[T_WHILE]); + unset($commentOpeners[T_FOR]); + unset($commentOpeners[T_FOREACH]); + unset($commentOpeners[T_DO]); + unset($commentOpeners[T_TRY]); + + do { + switch ($tokens[$next]['code']) { + case T_DOC_COMMENT_OPEN_TAG: + if ($foundDocblock === true) { + // Found a second docblock, so start of code. + break(2); + } + + // Make sure this is not a code-level docblock. + $end = $tokens[$next]['comment_closer']; + for ($docToken = ($end + 1); $docToken < $phpcsFile->numTokens; $docToken++) { + if (isset(Tokens::$emptyTokens[$tokens[$docToken]['code']]) === true) { + continue; + } + + if ($tokens[$docToken]['code'] === T_ATTRIBUTE + && isset($tokens[$docToken]['attribute_closer']) === true + ) { + $docToken = $tokens[$docToken]['attribute_closer']; + continue; + } + + break; + } + + if ($docToken === $phpcsFile->numTokens) { + $docToken--; + } + + if (isset($commentOpeners[$tokens[$docToken]['code']]) === false + && isset(Tokens::$methodPrefixes[$tokens[$docToken]['code']]) === false + ) { + // Check for an @var annotation. + $annotation = false; + for ($i = $next; $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG + && strtolower($tokens[$i]['content']) === '@var' + ) { + $annotation = true; + break; + } + } + + if ($annotation === false) { + $foundDocblock = true; + $headerLines[] = [ + 'type' => 'docblock', + 'start' => $next, + 'end' => $end, + ]; + } + }//end if + + $next = $end; + break; + case T_DECLARE: + case T_NAMESPACE: + if (isset($tokens[$next]['scope_opener']) === true) { + // If this statement is using bracketed syntax, it doesn't + // apply to the entire files and so is not part of header. + // The header has now ended and the main code block begins. + break(2); + } + + $end = $phpcsFile->findEndOfStatement($next); + + $headerLines[] = [ + 'type' => substr(strtolower($tokens[$next]['type']), 2), + 'start' => $next, + 'end' => $end, + ]; + + $next = $end; + break; + case T_USE: + $type = 'use'; + $useType = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($useType !== false && $tokens[$useType]['code'] === T_STRING) { + $content = strtolower($tokens[$useType]['content']); + if ($content === 'function' || $content === 'const') { + $type .= ' '.$content; + } + } + + $end = $phpcsFile->findEndOfStatement($next); + + $headerLines[] = [ + 'type' => $type, + 'start' => $next, + 'end' => $end, + ]; + + $next = $end; + break; + default: + // Skip comments as PSR-12 doesn't say if these are allowed or not. + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true) { + $next = $phpcsFile->findNext(Tokens::$commentTokens, ($next + 1), null, true); + if ($next === false) { + // We reached the end of the file. + break(2); + } + + $next--; + break; + } + + // We found the start of the main code block. + break(2); + }//end switch + + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + } while ($next !== false); + + return $headerLines; + + }//end getHeaderLines() + + + /** + * Check the spacing and grouping of the statements inside each header block. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $headerLines Header information, as sourced + * from getHeaderLines(). + * + * @return int|null + */ + public function processHeaderLines(File $phpcsFile, $headerLines) + { + $tokens = $phpcsFile->getTokens(); + + $found = []; + + foreach ($headerLines as $i => $line) { + if (isset($headerLines[($i + 1)]) === false + || $headerLines[($i + 1)]['type'] !== $line['type'] + ) { + // We're at the end of the current header block. + // Make sure there is a single blank line after + // this block. + $next = $phpcsFile->findNext(T_WHITESPACE, ($line['end'] + 1), null, true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$line['end']]['line'] + 2)) { + $error = 'Header blocks must be separated by a single blank line'; + $fix = $phpcsFile->addFixableError($error, $line['end'], 'SpacingAfterBlock'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$line['end']]['line']) { + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($tokens[$next]['line'] === ($tokens[$line['end']]['line'] + 1)) { + $phpcsFile->fixer->addNewline($line['end']); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($line['end'] + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === ($tokens[$line['end']]['line'] + 2)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + // Make sure we haven't seen this next block before. + if (isset($headerLines[($i + 1)]) === true + && isset($found[$headerLines[($i + 1)]['type']]) === true + ) { + $error = 'Similar statements must be grouped together inside header blocks; '; + $error .= 'the first "%s" statement was found on line %s'; + $data = [ + $headerLines[($i + 1)]['type'], + $tokens[$found[$headerLines[($i + 1)]['type']]['start']]['line'], + ]; + $phpcsFile->addError($error, $headerLines[($i + 1)]['start'], 'IncorrectGrouping', $data); + } + } else if ($headerLines[($i + 1)]['type'] === $line['type']) { + // Still in the same block, so make sure there is no + // blank line after this statement. + $next = $phpcsFile->findNext(T_WHITESPACE, ($line['end'] + 1), null, true); + if ($tokens[$next]['line'] > ($tokens[$line['end']]['line'] + 1)) { + $error = 'Header blocks must not contain blank lines'; + $fix = $phpcsFile->addFixableError($error, $line['end'], 'SpacingInsideBlock'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($line['end'] + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$line['end']]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + if (isset($found[$line['type']]) === false) { + $found[$line['type']] = $line; + } + }//end foreach + + /* + Next, check that the order of the header blocks + is correct: + Opening php tag. + File-level docblock. + One or more declare statements. + The namespace declaration of the file. + One or more class-based use import statements. + One or more function-based use import statements. + One or more constant-based use import statements. + */ + + $blockOrder = [ + 'tag' => 'opening PHP tag', + 'docblock' => 'file-level docblock', + 'declare' => 'declare statements', + 'namespace' => 'namespace declaration', + 'use' => 'class-based use imports', + 'use function' => 'function-based use imports', + 'use const' => 'constant-based use imports', + ]; + + foreach (array_keys($found) as $type) { + if ($type === 'tag') { + // The opening tag is always in the correct spot. + continue; + } + + do { + $orderedType = next($blockOrder); + } while ($orderedType !== false && key($blockOrder) !== $type); + + if ($orderedType === false) { + // We didn't find the block type in the rest of the + // ordered array, so it is out of place. + // Error and reset the array to the correct position + // so we can check the next block. + reset($blockOrder); + $prevValidType = 'tag'; + do { + $orderedType = next($blockOrder); + if (isset($found[key($blockOrder)]) === true + && key($blockOrder) !== $type + ) { + $prevValidType = key($blockOrder); + } + } while ($orderedType !== false && key($blockOrder) !== $type); + + $error = 'The %s must follow the %s in the file header'; + $data = [ + $blockOrder[$type], + $blockOrder[$prevValidType], + ]; + $phpcsFile->addError($error, $found[$type]['start'], 'IncorrectOrder', $data); + }//end if + }//end foreach + + }//end processHeaderLines() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php new file mode 100644 index 000000000..176aef006 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ImportStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is not a closure USE group. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return; + } + + if ($phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens) === true) { + // This rule only applies to import statements. + return; + } + + if ($tokens[$next]['code'] === T_STRING + && (strtolower($tokens[$next]['content']) === 'function' + || strtolower($tokens[$next]['content']) === 'const') + ) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + } + + if ($tokens[$next]['code'] !== T_NS_SEPARATOR) { + return; + } + + $error = 'Import statements must not begin with a leading backslash'; + $fix = $phpcsFile->addFixableError($error, $next, 'LeadingSlash'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php new file mode 100644 index 000000000..4371bee19 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OpenTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($stackPtr !== 0) { + // This rule only applies if the open tag is on the first line of the file. + return $phpcsFile->numTokens; + } + + $next = $phpcsFile->findNext(T_INLINE_HTML, 0); + if ($next !== false) { + // This rule only applies to PHP-only files. + return $phpcsFile->numTokens; + } + + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + // Empty file. + return; + } + + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAlone'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($stackPtr); + } + } + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php new file mode 100644 index 000000000..8d9073431 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NullableTypeDeclarationSniff implements Sniff +{ + + /** + * An array of valid tokens after `T_NULLABLE` occurrences. + * + * @var array + */ + private $validTokens = [ + T_STRING => true, + T_NS_SEPARATOR => true, + T_CALLABLE => true, + T_SELF => true, + T_PARENT => true, + T_STATIC => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NULLABLE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $nextNonEmptyPtr = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($nextNonEmptyPtr === false) { + // Parse error or live coding. + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextNonEmptyCode = $tokens[$nextNonEmptyPtr]['code']; + $validTokenFound = isset($this->validTokens[$nextNonEmptyCode]); + + if ($validTokenFound === true && $nextNonEmptyPtr === ($stackPtr + 1)) { + // Valid structure. + return; + } + + $error = 'There must not be a space between the question mark and the type in nullable type declarations'; + + if ($validTokenFound === true) { + // No other tokens then whitespace tokens found; fixable. + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WhitespaceFound'); + if ($fix === true) { + for ($i = ($stackPtr + 1); $i < $nextNonEmptyPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + return; + } + + // Non-whitespace tokens found; trigger error but don't fix. + $phpcsFile->addError($error, $stackPtr, 'UnexpectedCharactersFound'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php new file mode 100644 index 000000000..14d91e2ea --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php @@ -0,0 +1,110 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ReturnTypeDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $methodProperties = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProperties['return_type'] === '') { + return; + } + + $returnType = $methodProperties['return_type_token']; + if ($methodProperties['nullable_return_type'] === true) { + $returnType = $phpcsFile->findPrevious(T_NULLABLE, ($returnType - 1)); + } + + if ($tokens[($returnType - 1)]['code'] !== T_WHITESPACE + || $tokens[($returnType - 1)]['content'] !== ' ' + || $tokens[($returnType - 2)]['code'] !== T_COLON + ) { + $error = 'There must be a single space between the colon and type in a return type declaration'; + if ($tokens[($returnType - 1)]['code'] === T_WHITESPACE + && $tokens[($returnType - 2)]['code'] === T_COLON + ) { + $fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($returnType - 1), ' '); + } + } else if ($tokens[($returnType - 1)]['code'] === T_COLON) { + $fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($returnType, ' '); + } + } else { + $phpcsFile->addError($error, $returnType, 'SpaceBeforeReturnType'); + } + } + + $colon = $phpcsFile->findPrevious(T_COLON, $returnType); + if ($tokens[($colon - 1)]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'There must not be a space before the colon in a return type declaration'; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($colon - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { + $fix = $phpcsFile->addFixableError($error, $colon, 'SpaceBeforeColon'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($prev + 1); $x < $colon; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $colon, 'SpaceBeforeColon'); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php new file mode 100644 index 000000000..adf04d908 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Keywords; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ShortFormTypeKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_BOOL_CAST, + T_INT_CAST, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $typecast = str_replace(' ', '', $tokens[$stackPtr]['content']); + $typecast = str_replace("\t", '', $typecast); + $typecast = trim($typecast, '()'); + $typecastLc = strtolower($typecast); + + if (($tokens[$stackPtr]['code'] === T_BOOL_CAST + && $typecastLc === 'bool') + || ($tokens[$stackPtr]['code'] === T_INT_CAST + && $typecastLc === 'int') + ) { + return; + } + + $error = 'Short form type keywords must be used. Found: %s'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'LongFound', $data); + if ($fix === true) { + if ($tokens[$stackPtr]['code'] === T_BOOL_CAST) { + $replacement = str_replace($typecast, 'bool', $tokens[$stackPtr]['content']); + } else { + $replacement = str_replace($typecast, 'int', $tokens[$stackPtr]['content']); + } + + $phpcsFile->fixer->replaceToken($stackPtr, $replacement); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php new file mode 100644 index 000000000..725fbde31 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CompoundNamespaceDepthSniff implements Sniff +{ + + /** + * The max depth for compound namespaces. + * + * @var integer + */ + public $maxDepth = 2; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_USE_GROUP]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->maxDepth = (int) $this->maxDepth; + + $tokens = $phpcsFile->getTokens(); + + $end = $phpcsFile->findNext(T_CLOSE_USE_GROUP, ($stackPtr + 1)); + if ($end === false) { + return; + } + + $depth = 1; + for ($i = ($stackPtr + 1); $i <= $end; $i++) { + if ($tokens[$i]['code'] === T_NS_SEPARATOR) { + $depth++; + continue; + } + + if ($i === $end || $tokens[$i]['code'] === T_COMMA) { + // End of a namespace. + if ($depth > $this->maxDepth) { + $error = 'Compound namespaces cannot have a depth more than %s'; + $data = [$this->maxDepth]; + $phpcsFile->addError($error, $i, 'TooDeep', $data); + } + + $depth = 1; + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php new file mode 100644 index 000000000..8757e05a3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php @@ -0,0 +1,112 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\OperatorSpacingSniff as SquizOperatorSpacingSniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorSpacingSniff extends SquizOperatorSpacingSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + parent::register(); + + $targets = Tokens::$comparisonTokens; + $targets += Tokens::$operators; + $targets += Tokens::$assignmentTokens; + $targets += Tokens::$booleanOperators; + $targets[] = T_INLINE_THEN; + $targets[] = T_INLINE_ELSE; + $targets[] = T_STRING_CONCAT; + $targets[] = T_INSTANCEOF; + + return $targets; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->isOperator($phpcsFile, $stackPtr) === false) { + return; + } + + $operator = $tokens[$stackPtr]['content']; + + $checkBefore = true; + $checkAfter = true; + + // Skip short ternary. + if ($tokens[($stackPtr)]['code'] === T_INLINE_ELSE + && $tokens[($stackPtr - 1)]['code'] === T_INLINE_THEN + ) { + $checkBefore = false; + } + + // Skip operator with comment on previous line. + if ($tokens[($stackPtr - 1)]['code'] === T_COMMENT + && $tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] + ) { + $checkBefore = false; + } + + if (isset($tokens[($stackPtr + 1)]) === true) { + // Skip short ternary. + if ($tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[($stackPtr + 1)]['code'] === T_INLINE_ELSE + ) { + $checkAfter = false; + } + } else { + // Skip partial files. + $checkAfter = false; + } + + if ($checkBefore === true && $tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected at least 1 space before "%s"; 0 found'; + $data = [$operator]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } + + if ($checkAfter === true && $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected at least 1 space after "%s"; 0 found'; + $data = [$operator]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php new file mode 100644 index 000000000..7f63d1e87 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Properties; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConstantVisibilitySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CONST]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is a class constant. + if ($phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens) === false) { + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_FINAL; + + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + if (isset(Tokens::$scopeModifiers[$tokens[$prev]['code']]) === true) { + return; + } + + $error = 'Visibility must be declared on all constants if your project supports PHP 7.1 or later'; + $phpcsFile->addWarning($error, $stackPtr, 'NotFound'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php new file mode 100644 index 000000000..113e8b9f8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php @@ -0,0 +1,700 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Traits; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Needs to be a use statement directly inside a class. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + if (isset(Tokens::$ooScopeTokens[current($conditions)]) === false) { + return; + } + + $ooToken = key($conditions); + $opener = $tokens[$ooToken]['scope_opener']; + + // Figure out where all the use statements are. + $useTokens = [$stackPtr]; + for ($i = ($stackPtr + 1); $i < $tokens[$ooToken]['scope_closer']; $i++) { + if ($tokens[$i]['code'] === T_USE) { + $useTokens[] = $i; + } + + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + } + } + + $numUseTokens = count($useTokens); + foreach ($useTokens as $usePos => $useToken) { + if ($usePos === 0) { + /* + This is the first use statement. + */ + + // The first non-comment line must be the use line. + $lastValidContent = $useToken; + for ($i = ($useToken - 1); $i > $opener; $i--) { + if ($tokens[$i]['code'] === T_WHITESPACE + && ($tokens[($i - 1)]['line'] === $tokens[$i]['line'] + || $tokens[($i + 1)]['line'] === $tokens[$i]['line']) + ) { + continue; + } + + if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past the comment. + $i = $tokens[$i]['comment_opener']; + } + + $lastValidContent = $i; + + continue; + } + + break; + }//end for + + if ($tokens[$lastValidContent]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'The first trait import statement must be declared on the first non-comment line after the %s opening brace'; + $data = [strtolower($tokens[$ooToken]['content'])]; + + // Figure out if we can fix this error. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($useToken - 1), ($opener - 1), true); + if ($tokens[$prev]['line'] === $tokens[$opener]['line']) { + $fix = $phpcsFile->addFixableError($error, $useToken, 'UseAfterBrace', $data); + if ($fix === true) { + // We know that the USE statements is the first non-comment content + // in the class, so we just need to remove blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($useToken - 1); $i > $opener; $i--) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + break; + } + + if ($tokens[$i]['line'] === $tokens[$useToken]['line']) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[($i - 1)]['line'] !== $tokens[$i]['line'] + && $tokens[($i + 1)]['line'] !== $tokens[$i]['line'] + ) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past the comment. + $i = $tokens[$i]['comment_opener']; + } + + $lastValidContent = $i; + } + }//end for + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $phpcsFile->addError($error, $useToken, 'UseAfterBrace', $data); + }//end if + }//end if + } else { + // Make sure this use statement is not on the same line as the previous one. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($useToken - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$useToken]['line']) { + $error = 'Each imported trait must be on its own line'; + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($useToken - 1), null, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $useToken, 'SpacingBeforeImport'); + } else { + $fix = $phpcsFile->addFixableError($error, $useToken, 'SpacingBeforeImport'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($useToken - 1); $x > $prev; $x--) { + if ($tokens[$x]['line'] === $tokens[$useToken]['line'] + ) { + // Preserve indent. + continue; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($prev); + if ($tokens[$prev]['line'] === $tokens[$useToken]['line']) { + if ($tokens[($useToken - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($useToken - 1), ''); + } + + $padding = str_repeat(' ', ($tokens[$useTokens[0]]['column'] - 1)); + $phpcsFile->fixer->addContent($prev, $padding); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Check the formatting of the statement. + if (isset($tokens[$useToken]['scope_opener']) === true) { + $this->processUseGroup($phpcsFile, $useToken); + $end = $tokens[$useToken]['scope_closer']; + } else { + $this->processUseStatement($phpcsFile, $useToken); + $end = $phpcsFile->findNext(T_SEMICOLON, ($useToken + 1)); + if ($end === false) { + // Syntax error. + return; + } + } + + if ($usePos === ($numUseTokens - 1)) { + /* + This is the last use statement. + */ + + $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true); + if ($next === $tokens[$ooToken]['scope_closer']) { + // Last content in the class. + $closer = $tokens[$ooToken]['scope_closer']; + if ($tokens[$closer]['line'] > ($tokens[$end]['line'] + 1)) { + $error = 'There must be no blank line after the last trait import statement at the bottom of a %s'; + $data = [strtolower($tokens[$ooToken]['content'])]; + $fix = $phpcsFile->addFixableError($error, $end, 'BlankLineAfterLastUse', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($end + 1); $i < $closer; $i++) { + if ($tokens[$i]['line'] === $tokens[$end]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$closer]['line']) { + // Don't remove indents. + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else if ($tokens[$next]['code'] !== T_USE) { + // Comments are allowed on the same line as the use statement, so make sure + // we don't error for those. + for ($next = ($end + 1); $next < $tokens[$ooToken]['scope_closer']; $next++) { + if ($tokens[$next]['code'] === T_WHITESPACE) { + continue; + } + + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$end]['line'] + ) { + continue; + } + + break; + } + + if ($tokens[$next]['line'] <= ($tokens[$end]['line'] + 1)) { + $error = 'There must be a blank line following the last trait import statement'; + $fix = $phpcsFile->addFixableError($error, $end, 'NoBlankLineAfterUse'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$useToken]['line']) { + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else { + for ($i = ($next - 1); $i > $end; $i--) { + if ($tokens[$i]['line'] !== $tokens[$next]['line']) { + break; + } + } + + $phpcsFile->fixer->addNewlineBefore(($i + 1)); + } + } + } + }//end if + } else { + // Ensure use statements are grouped. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next !== $useTokens[($usePos + 1)]) { + $error = 'Imported traits must be grouped together'; + $phpcsFile->addError($error, $useTokens[($usePos + 1)], 'NotGrouped'); + } + }//end if + }//end foreach + + return $tokens[$ooToken]['scope_closer']; + + }//end process() + + + /** + * Processes a group use statement. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processUseGroup(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $opener = $tokens[$stackPtr]['scope_opener']; + $closer = $tokens[$stackPtr]['scope_closer']; + + if ($tokens[$opener]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'The opening brace of a trait import statement must be on the same line as the USE keyword'; + // Figure out if we can fix this error. + $canFix = true; + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + && $tokens[$i]['code'] !== T_WHITESPACE + ) { + $canFix = false; + break; + } + } + + if ($canFix === true) { + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceNewLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['line'] !== $tokens[($i + 1)]['line']) { + // Everything should have a single space around it. + $phpcsFile->fixer->replaceToken($i, ' '); + } + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $opener, 'OpenBraceNewLine'); + } + }//end if + + $error = 'Expected 1 space before opening brace in trait import statement; %s found'; + if ($tokens[($opener - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceBeforeOpeningBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($opener, ' '); + } + } else if ($tokens[($opener - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), null, true); + if ($tokens[$prev]['line'] !== $tokens[$opener]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($opener - 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceBeforeOpeningBrace', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($opener - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($opener, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($opener - 1), ' '); + } + } + }//end if + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($opener + 1), ($closer - 1), true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'First trait conflict resolution statement must be on the line after the opening brace'; + $nextNonWs = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), ($closer - 1), true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $opener, 'SpaceAfterOpeningBrace'); + } else { + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceAfterOpeningBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($opener + 1); $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + // Preserve indent. + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($opener); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + if ($tokens[($i - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected no space before comma in trait import statement; %s found'; + $data = [$tokens[($i - 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i - 1), ''); + } + } + + $error = 'Expected 1 space after comma in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $opener, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterComma', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + }//end if + }//end for + + for ($i = ($opener + 1); $i < $closer; $i++) { + if ($tokens[$i]['code'] === T_INSTEADOF) { + $error = 'Expected 1 space before INSTEADOF in trait import statement; %s found'; + if ($tokens[($i - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeInsteadof', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($i, ' '); + } + } else if ($tokens[($i - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), $opener, true); + if ($tokens[$prev]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i - 1)]['length']; + } + + $data = [$found]; + + $prevNonWs = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $opener, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $i, 'SpaceBeforeInsteadof', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeInsteadof', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), ' '); + } + } + } + }//end if + + $error = 'Expected 1 space after INSTEADOF in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterInsteadof', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $closer, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closer, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'SpaceAfterInsteadof', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterInsteadof', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + } + }//end if + }//end if + + if ($tokens[$i]['code'] === T_AS) { + $error = 'Expected 1 space before AS in trait import statement; %s found'; + if ($tokens[($i - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($i, ' '); + } + } else if ($tokens[($i - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), $opener, true); + if ($tokens[$prev]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i - 1)]['length']; + } + + $data = [$found]; + + $prevNonWs = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $opener, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $i, 'SpaceBeforeAs', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), ' '); + } + } + } + }//end if + + $error = 'Expected 1 space after AS in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $closer, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closer, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'SpaceAfterAs', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + } + }//end if + }//end if + + if ($tokens[$i]['code'] === T_SEMICOLON) { + if ($tokens[($i - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected no space before semicolon in trait import statement; %s found'; + $data = [$tokens[($i - 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i - 1), ''); + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), ($closer - 1), true); + if ($next !== false && $tokens[$next]['line'] === $tokens[$i]['line']) { + $error = 'Each trait conflict resolution statement must be on a line by itself'; + $nextNonWs = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closer - 1), true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'ConflictSameLine'); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'ConflictSameLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[($i + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($i + 1), ''); + } + + $phpcsFile->fixer->addNewline($i); + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end for + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closer - 1), ($opener + 1), true); + if ($prev !== false && $tokens[$prev]['line'] !== ($tokens[$closer]['line'] - 1)) { + $error = 'Closing brace must be on the line after the last trait conflict resolution statement'; + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), ($opener + 1), true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $closer, 'SpaceBeforeClosingBrace'); + } else { + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeClosingBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($closer - 1); $x > $prev; $x--) { + if ($tokens[$x]['line'] === $tokens[$closer]['line']) { + // Preserve indent. + continue; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processUseGroup() + + + /** + * Processes a single use statement. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processUseStatement(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $error = 'Expected 1 space after USE in trait import statement; %s found'; + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($stackPtr + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($stackPtr, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + $next = $phpcsFile->findNext([T_COMMA, T_SEMICOLON], ($stackPtr + 1)); + if ($next !== false && $tokens[$next]['code'] === T_COMMA) { + $error = 'Each imported trait must have its own "use" import statement'; + $fix = $phpcsFile->addFixableError($error, $next, 'MultipleImport'); + if ($fix === true) { + $padding = str_repeat(' ', ($tokens[$stackPtr]['column'] - 1)); + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar.$padding.'use '); + } + } + + }//end processUseStatement() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc new file mode 100644 index 000000000..e132b54df --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc @@ -0,0 +1,84 @@ +bar( + new class implements Bar { + // ... + }, +); + +foo(new class { +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..921dcc02d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed @@ -0,0 +1,86 @@ +bar( + new class implements Bar { + // ... + }, +); + +foo(new class { +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php new file mode 100644 index 000000000..cc162b290 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class AnonClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 28 => 3, + 30 => 1, + 31 => 4, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 3, + 39 => 1, + 40 => 1, + 43 => 3, + 44 => 4, + 45 => 1, + 48 => 1, + 52 => 3, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 2, + 63 => 1, + 75 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc new file mode 100644 index 000000000..d933ee273 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc @@ -0,0 +1,44 @@ +bar(); +echo (new Foo)->bar(); +echo (new Foo((new Bar)->getBaz()))->bar(); +$foo = (new Foo)::$bar; + +echo (new Foo((new Bar//comment +)->getBaz(new Baz /* comment */)))->bar(); + +$foo = new $bar['a'](); +$foo = new $bar['a']['b'](); +$foo = new $bar['a'][$baz['a']['b']]['b'](); +$foo = new $bar['a'] [$baz['a']/* comment */ ['b']]['b']; + +$a = new self::$transport[$cap_string]; +$renderer = new $this->inline_diff_renderer; +$a = new ${$varHoldingClassName}; + +$class = new $obj?->classname(); +$class = new $obj?->classname; +$class = new ${$obj?->classname}; + +// Issue 3456. +// Anon classes should be skipped, even when there is an attribute between the new and the class keywords. +$anonWithAttribute = new #[SomeAttribute('summary')] class { + public const SOME_STUFF = 'foo'; +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed new file mode 100644 index 000000000..02e3544fa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed @@ -0,0 +1,44 @@ +bar(); +echo (new Foo())->bar(); +echo (new Foo((new Bar())->getBaz()))->bar(); +$foo = (new Foo())::$bar; + +echo (new Foo((new Bar()//comment +)->getBaz(new Baz() /* comment */)))->bar(); + +$foo = new $bar['a'](); +$foo = new $bar['a']['b'](); +$foo = new $bar['a'][$baz['a']['b']]['b'](); +$foo = new $bar['a'] [$baz['a']/* comment */ ['b']]['b'](); + +$a = new self::$transport[$cap_string](); +$renderer = new $this->inline_diff_renderer(); +$a = new ${$varHoldingClassName}(); + +$class = new $obj?->classname(); +$class = new $obj?->classname(); +$class = new ${$obj?->classname}(); + +// Issue 3456. +// Anon classes should be skipped, even when there is an attribute between the new and the class keywords. +$anonWithAttribute = new #[SomeAttribute('summary')] class { + public const SOME_STUFF = 'foo'; +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php new file mode 100644 index 000000000..3fb1ab992 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassInstantiationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 9 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 24 => 1, + 25 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 37 => 1, + 38 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc new file mode 100644 index 000000000..2562d26c0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc @@ -0,0 +1,52 @@ +bar( + $arg1, + function ($arg2) use ($var1) { + // body + }, + $arg3 +); + +$instance = new class extends \Foo implements \HandleableInterface { + // Class content +}; + +$app->get('/hello/{name}', function ($name) use ($app) { + return 'Hello ' . $app->escape($name); +}); + +enum Foo4 +{ + +}//end diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php new file mode 100644 index 000000000..d402f1bb9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 14 => 1, + 19 => 1, + 24 => 1, + 31 => 1, + 52 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc new file mode 100644 index 000000000..2c41bde99 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 18 => 1, + 24 => 1, + 34 => 1, + 41 => 1, + 55 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc new file mode 100644 index 000000000..4bc2eceba --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc @@ -0,0 +1,131 @@ + 0 && $n < 10) + || ($n > 10 && $n < 20) + || ($n > 20 && $n < 30) +) { + return $n; +} + +if ( + ( + $expr1 + && $expr2 + && $expr3 + && $expr4 + && $expr5 + && $expr6 + ) + || ($n > 100 && $n < 200) + || ($n > 200 && $n < 300) +) { + return $n; +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly first +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 || $expr4) && + $expr5 +) { + // elseif body +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly last +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 || $expr4) && + $expr5 +) { + // elseif body +} + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} + +// Reset to default. +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly + +match ( + $expr1 + && $expr2 && + $expr3 +) { + // structure body +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed new file mode 100644 index 000000000..5f4d223e8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed @@ -0,0 +1,141 @@ + 0 && $n < 10) + || ($n > 10 && $n < 20) + || ($n > 20 && $n < 30) +) { + return $n; +} + +if ( + ( + $expr1 + && $expr2 + && $expr3 + && $expr4 + && $expr5 + && $expr6 + ) + || ($n > 100 && $n < 200) + || ($n > 200 && $n < 300) +) { + return $n; +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly first +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 + && ($expr3 + || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 + || $expr4) + && $expr5 +) { + // elseif body +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly last +if ( + $expr1 && + $expr2 && + ($expr3 || + $expr4) && + $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || + $expr4) && + $expr5 +) { + // elseif body +} elseif ( + $expr1 && + ($expr3 || + $expr4) && + $expr5 +) { + // elseif body +} + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} + +// Reset to default. +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly + +match ( + $expr1 + && $expr2 + && $expr3 +) { + // structure body +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php new file mode 100644 index 000000000..3eeaeebc4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class BooleanOperatorPlacementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 16 => 1, + 28 => 1, + 34 => 1, + 75 => 1, + 81 => 1, + 90 => 1, + 98 => 1, + 104 => 1, + 125 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc new file mode 100644 index 000000000..9c037d6cd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,100 @@ + $foo + /* + * A multi-line comment. + */ + && $foo === true + ) { + break; + } + +match ( + $expr1 && + $expr2 && + $expr3 + ) { + // structure body +}; + +match ($expr1 && +$expr2 && + $expr3) { + // structure body +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..7ea61b1e2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,103 @@ + $foo + /* + * A multi-line comment. + */ + && $foo === true + ) { + break; + } + +match ( + $expr1 && + $expr2 && + $expr3 +) { + // structure body +}; + +match ( + $expr1 && + $expr2 && + $expr3 +) { + // structure body +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php new file mode 100644 index 000000000..6ee076f2e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 2, + 16 => 1, + 17 => 1, + 18 => 1, + 22 => 1, + 23 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 48 => 2, + 58 => 1, + 59 => 1, + 92 => 1, + 96 => 1, + 97 => 1, + 98 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc new file mode 100644 index 000000000..f21daaff4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.inc @@ -0,0 +1,50 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DeclareStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 9 => 2, + 10 => 1, + 11 => 3, + 12 => 2, + 13 => 1, + 14 => 2, + 16 => 3, + 19 => 3, + 22 => 1, + 24 => 1, + 26 => 3, + 28 => 3, + 34 => 2, + 43 => 1, + 46 => 1, + 47 => 1, + 49 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc new file mode 100644 index 000000000..1298ed71b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc @@ -0,0 +1,29 @@ + + +

    + + + +

    + + + + +

    Demo

    + + +
  • My page
  • +
  • Write
  • +
  • Sign out
  • + +
  • Sign in
  • + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc new file mode 100644 index 000000000..11102beb6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc @@ -0,0 +1,5 @@ + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc new file mode 100644 index 000000000..5c3df1f37 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc @@ -0,0 +1,13 @@ + + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileHeaderUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileHeaderUnitTest.2.inc': + return [ + 1 => 1, + 6 => 1, + 7 => 1, + 18 => 1, + 20 => 1, + 24 => 1, + ]; + case 'FileHeaderUnitTest.3.inc': + return [ + 9 => 1, + 18 => 1, + ]; + case 'FileHeaderUnitTest.4.inc': + return [ + 1 => 1, + 2 => 1, + 3 => 1, + 7 => 1, + ]; + case 'FileHeaderUnitTest.5.inc': + return [4 => 1]; + case 'FileHeaderUnitTest.7.inc': + case 'FileHeaderUnitTest.10.inc': + case 'FileHeaderUnitTest.11.inc': + return [1 => 1]; + case 'FileHeaderUnitTest.12.inc': + return [4 => 2]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc new file mode 100644 index 000000000..6d024eaa9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ImportStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 7 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc new file mode 100644 index 000000000..0dbdf010a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc @@ -0,0 +1,3 @@ + +hi diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc new file mode 100644 index 000000000..09be8fbe6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc @@ -0,0 +1,2 @@ + + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OpenTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'OpenTagUnitTest.2.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc new file mode 100644 index 000000000..e3a5a775f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc @@ -0,0 +1,87 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NullableTypeDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 23 => 1, + 24 => 1, + 25 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 43 => 2, + 48 => 1, + 50 => 1, + 51 => 1, + 53 => 1, + 57 => 2, + 58 => 2, + 59 => 2, + 87 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc new file mode 100644 index 000000000..59ab1aa78 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc @@ -0,0 +1,66 @@ + $arg; + +return (!$a ? [ new class { public function b(): c {} } ] : []); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..cd79f7816 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed @@ -0,0 +1,62 @@ + $arg; + +return (!$a ? [ new class { public function b(): c {} } ] : []); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php new file mode 100644 index 000000000..fc6b5e19c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ReturnTypeDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 27 => 1, + 28 => 1, + 35 => 2, + 41 => 2, + 48 => 2, + 52 => 1, + 55 => 1, + 56 => 1, + 59 => 1, + 60 => 1, + 62 => 1, + 64 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc new file mode 100644 index 000000000..6ce930d94 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Keywords; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ShortFormTypeKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 13 => 1, + 14 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc new file mode 100644 index 000000000..3336fc2dc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc @@ -0,0 +1,31 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CompoundNamespaceDepthUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 18 => 1, + 21 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc new file mode 100644 index 000000000..c067e6a2a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc @@ -0,0 +1,77 @@ + $b) { + $variable =$foo ? 'foo' :'bar'; + $variable.='text'.'text'; +} + +$foo+= $a&$b; +$foo = $a|$b; +$foo =$a^$b; +$foo = ~$a; +$foo *=$a<<$b; +$foo = $a>>$b; + +function foo(&$a,& $b) {} + +$foo = $a and$b; +$foo = $a or $b; +$foo = $a xor$b; +$foo = !$a; +$foo = $a&&$b; +$foo = $a||$b; + +$foo = $a instanceof Foo; +$foo = $a instanceof$b; + +$foo .= 'hi' + .= 'there'; + +$foo .= 'hi' +.= 'there'; + +$foo .= 'hi' // comment +.= 'there'; + +$foo/*comment*/=/*comment*/$a/*comment*/and/*comment*/$b; + +$foo .=//comment +'string' .=/*comment*/ +'string'; + +$foo = $foo ?: 'bar'; +$foo = $foo?:'bar'; + +try { +} catch (ExceptionType1|ExceptionType2 $e) { +} + +if (strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') {} + +$oldConstructorPos = +1; +return -$content; + +function name($a = -1) {} + +$a =& $ref; +$a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +function issue3267(string|int ...$values) {} + +function setDefault(#[ImportValue( + constraints: [ + [ + Assert\Type::class, + ['type' => 'bool'], + ], + ] + )] ?bool $value = null): void + { + // Do something + } diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..76764291f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,77 @@ + $b) { + $variable = $foo ? 'foo' : 'bar'; + $variable .= 'text' . 'text'; +} + +$foo += $a & $b; +$foo = $a | $b; +$foo = $a ^ $b; +$foo = ~$a; +$foo *= $a << $b; +$foo = $a >> $b; + +function foo(&$a,& $b) {} + +$foo = $a and $b; +$foo = $a or $b; +$foo = $a xor $b; +$foo = !$a; +$foo = $a && $b; +$foo = $a || $b; + +$foo = $a instanceof Foo; +$foo = $a instanceof $b; + +$foo .= 'hi' + .= 'there'; + +$foo .= 'hi' +.= 'there'; + +$foo .= 'hi' // comment +.= 'there'; + +$foo/*comment*/ = /*comment*/$a/*comment*/ and /*comment*/$b; + +$foo .= //comment +'string' .= /*comment*/ +'string'; + +$foo = $foo ?: 'bar'; +$foo = $foo ?: 'bar'; + +try { +} catch (ExceptionType1 | ExceptionType2 $e) { +} + +if (strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') {} + +$oldConstructorPos = +1; +return -$content; + +function name($a = -1) {} + +$a =& $ref; +$a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +function issue3267(string|int ...$values) {} + +function setDefault(#[ImportValue( + constraints: [ + [ + Assert\Type::class, + ['type' => 'bool'], + ], + ] + )] ?bool $value = null): void + { + // Do something + } diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php new file mode 100644 index 000000000..e23fd968b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 2, + 4 => 1, + 5 => 2, + 6 => 4, + 9 => 3, + 10 => 2, + 11 => 3, + 13 => 3, + 14 => 2, + 18 => 1, + 20 => 1, + 22 => 2, + 23 => 2, + 26 => 1, + 37 => 4, + 39 => 1, + 40 => 1, + 44 => 2, + 47 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc new file mode 100644 index 000000000..84ea24b2e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc @@ -0,0 +1,22 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Properties; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ConstantVisibilityUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + 21 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc new file mode 100644 index 000000000..c8ad746a7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc @@ -0,0 +1,221 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Traits; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 15 => 1, + 29 => 2, + 30 => 1, + 42 => 1, + 57 => 3, + 59 => 3, + 61 => 1, + 63 => 5, + 65 => 1, + 71 => 1, + 73 => 2, + 76 => 1, + 86 => 2, + 103 => 1, + 112 => 1, + 122 => 1, + 132 => 1, + 157 => 1, + 165 => 1, + 170 => 1, + 208 => 1, + 219 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml new file mode 100644 index 000000000..ce8b71a75 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml @@ -0,0 +1,347 @@ + + + The PSR-12 coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + Method name "%s" must not be prefixed with an underscore to indicate visibility + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 000000000..4e56bc04a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,23 @@ + + + + + + + class Foo +{ +} + ]]> + + + class Foo +{ +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml new file mode 100644 index 000000000..042c0c6cd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml @@ -0,0 +1,81 @@ + + + + + + + bar; +} + ]]> + + + _bar; +} + ]]> + + + + + private $bar; +} + ]]> + + + var $bar; +} + ]]> + + + + + + + + $bar, $baz; +} + ]]> + + + + + static $bar; + private $baz; +} + ]]> + + + static protected $bar; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml new file mode 100644 index 000000000..dcbe98f5e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $foo) { + $var = 1; +} + ]]> + + + $foo ) { + $var = 1; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml new file mode 100644 index 000000000..a22dd1796 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml @@ -0,0 +1,27 @@ + + + + + + + elseif ($bar) { + $var = 2; +} + ]]> + + + else if ($bar) { + $var = 2; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml new file mode 100644 index 000000000..1d6d053df --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml @@ -0,0 +1,104 @@ + + + + + + + case 'bar': + break; +} + ]]> + + + case 'bar': + break; +} + ]]> + + + + + 'bar': + break; +} + ]]> + + + 'bar': + break; +} + ]]> + + + + + : + break; + default: + break; +} + ]]> + + + : + break; + default : + break; +} + ]]> + + + + + break; +} + ]]> + + + break; +} + ]]> + + + + + // no break + default: + break; +} + ]]> + + + : + break; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml new file mode 100644 index 000000000..d6d3aad16 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml new file mode 100644 index 000000000..e45469e80 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml @@ -0,0 +1,51 @@ + + + + + + + bar() + { + } +} + ]]> + + + _bar() + { + } +} + ]]> + + + + + final public static function bar() + { + } +} + ]]> + + + static public final function bar() + { + } +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml new file mode 100644 index 000000000..1f4d389aa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml @@ -0,0 +1,22 @@ + + + + + + + +use \Baz; + ]]> + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml new file mode 100644 index 000000000..4082603ca --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml @@ -0,0 +1,57 @@ + + + + + + + + + + \Foo, \Bar; + ]]> + + + + + + + + + + + + + +class Baz +{ +} + ]]> + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..f96b00490 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,528 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDeclarationSniff as PEARClassDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDeclarationSniff extends PEARClassDeclarationSniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // We want all the errors from the PEAR standard, plus some of our own. + parent::process($phpcsFile, $stackPtr); + + // Just in case. + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $this->processOpen($phpcsFile, $stackPtr); + $this->processClose($phpcsFile, $stackPtr); + + }//end process() + + + /** + * Processes the opening section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processOpen(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $stackPtrType = strtolower($tokens[$stackPtr]['content']); + + // Check alignment of the keyword and braces. + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($stackPtr - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + + if (in_array($tokens[($stackPtr - 2)]['code'], [T_ABSTRACT, T_FINAL], true) === true + && $spaces !== 1 + ) { + $prevContent = strtolower($tokens[($stackPtr - 2)]['content']); + $error = 'Expected 1 space between %s and %s keywords; %s found'; + $data = [ + $prevContent, + $stackPtrType, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } else if ($tokens[($stackPtr - 2)]['code'] === T_ABSTRACT + || $tokens[($stackPtr - 2)]['code'] === T_FINAL + ) { + $prevContent = strtolower($tokens[($stackPtr - 2)]['content']); + $error = 'Expected 1 space between %s and %s keywords; newline found'; + $data = [ + $prevContent, + $stackPtrType, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NewlineBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + }//end if + }//end if + + // We'll need the indent of the class/interface declaration for later. + $classIndent = 0; + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } + + // We changed lines. + if ($tokens[($i + 1)]['code'] === T_WHITESPACE) { + $classIndent = $tokens[($i + 1)]['length']; + } + + break; + } + + $className = null; + $checkSpacing = true; + + if ($tokens[$stackPtr]['code'] !== T_ANON_CLASS) { + $className = $phpcsFile->findNext(T_STRING, $stackPtr); + } else { + // Ignore the spacing check if this is a simple anon class. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === $tokens[$stackPtr]['scope_opener'] + && $tokens[$next]['line'] > $tokens[$stackPtr]['line'] + ) { + $checkSpacing = false; + } + } + + if ($checkSpacing === true) { + // Spacing of the keyword. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $gap = 0; + } else if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $gap = 'newline'; + } else { + $gap = $tokens[($stackPtr + 1)]['length']; + } + + if ($gap !== 1) { + $error = 'Expected 1 space after %s keyword; %s found'; + $data = [ + $stackPtrType, + $gap, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword', $data); + if ($fix === true) { + if ($gap === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + }//end if + + // Check after the class/interface name. + if ($className !== null + && $tokens[($className + 2)]['line'] === $tokens[$className]['line'] + ) { + $gap = $tokens[($className + 1)]['content']; + if (strlen($gap) !== 1) { + $found = strlen($gap); + $error = 'Expected 1 space after %s name; %s found'; + $data = [ + $stackPtrType, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceAfterName', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($className + 1), ' '); + } + } + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + + // Check positions of the extends and implements keywords. + $compareToken = $stackPtr; + $compareType = 'name'; + if ($tokens[$stackPtr]['code'] === T_ANON_CLASS) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) { + $compareToken = $tokens[$stackPtr]['parenthesis_closer']; + $compareType = 'closing parenthesis'; + } else { + $compareType = 'keyword'; + } + } + + foreach (['extends', 'implements'] as $keywordType) { + $keyword = $phpcsFile->findNext(constant('T_'.strtoupper($keywordType)), ($compareToken + 1), $openingBrace); + if ($keyword !== false) { + if ($tokens[$keyword]['line'] !== $tokens[$compareToken]['line']) { + $error = 'The '.$keywordType.' keyword must be on the same line as the %s '.$compareType; + $data = [$stackPtrType]; + $fix = $phpcsFile->addFixableError($error, $keyword, ucfirst($keywordType).'Line', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $comments = []; + + for ($i = ($compareToken + 1); $i < $keyword; ++$i) { + if ($tokens[$i]['code'] === T_COMMENT) { + $comments[] = trim($tokens[$i]['content']); + } + + if ($tokens[$i]['code'] === T_WHITESPACE + || $tokens[$i]['code'] === T_COMMENT + ) { + $phpcsFile->fixer->replaceToken($i, ' '); + } + } + + $phpcsFile->fixer->addContent($compareToken, ' '); + if (empty($comments) === false) { + $i = $keyword; + while ($tokens[($i + 1)]['line'] === $tokens[$keyword]['line']) { + ++$i; + } + + $phpcsFile->fixer->addContentBefore($i, ' '.implode(' ', $comments)); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + // Check the whitespace before. Whitespace after is checked + // later by looking at the whitespace before the first class name + // in the list. + $gap = $tokens[($keyword - 1)]['length']; + if ($gap !== 1) { + $error = 'Expected 1 space before '.$keywordType.' keyword; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, $keyword, 'SpaceBefore'.ucfirst($keywordType), $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($keyword - 1), ' '); + } + } + }//end if + }//end if + }//end foreach + + // Check each of the extends/implements class names. If the extends/implements + // keyword is the last content on the line, it means we need to check for + // the multi-line format, so we do not include the class names + // from the extends/implements list in the following check. + // Note that classes can only extend one other class, so they can't use a + // multi-line extends format, whereas an interface can extend multiple + // other interfaces, and so uses a multi-line extends format. + if ($tokens[$stackPtr]['code'] === T_INTERFACE) { + $keywordTokenType = T_EXTENDS; + } else { + $keywordTokenType = T_IMPLEMENTS; + } + + $implements = $phpcsFile->findNext($keywordTokenType, ($stackPtr + 1), $openingBrace); + $multiLineImplements = false; + if ($implements !== false) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $implements, true); + if ($tokens[$prev]['line'] !== $tokens[$implements]['line']) { + $multiLineImplements = true; + } + } + + $find = [ + T_STRING, + $keywordTokenType, + ]; + + if ($className !== null) { + $start = $className; + } else if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $start = $tokens[$stackPtr]['parenthesis_closer']; + } else { + $start = $stackPtr; + } + + $classNames = []; + $nextClass = $phpcsFile->findNext($find, ($start + 2), ($openingBrace - 1)); + while ($nextClass !== false) { + $classNames[] = $nextClass; + $nextClass = $phpcsFile->findNext($find, ($nextClass + 1), ($openingBrace - 1)); + } + + $classCount = count($classNames); + $checkingImplements = false; + $implementsToken = null; + foreach ($classNames as $n => $className) { + if ($tokens[$className]['code'] === $keywordTokenType) { + $checkingImplements = true; + $implementsToken = $className; + + continue; + } + + if ($checkingImplements === true + && $multiLineImplements === true + && ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR + || $tokens[($className - 2)]['code'] !== T_STRING) + ) { + $prev = $phpcsFile->findPrevious( + [ + T_NS_SEPARATOR, + T_WHITESPACE, + ], + ($className - 1), + $implements, + true + ); + + if ($prev === $implementsToken && $tokens[$className]['line'] !== ($tokens[$prev]['line'] + 1)) { + if ($keywordTokenType === T_EXTENDS) { + $error = 'The first item in a multi-line extends list must be on the line following the extends keyword'; + $fix = $phpcsFile->addFixableError($error, $className, 'FirstExtendsInterfaceSameLine'); + } else { + $error = 'The first item in a multi-line implements list must be on the line following the implements keyword'; + $fix = $phpcsFile->addFixableError($error, $className, 'FirstInterfaceSameLine'); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $className; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$prev]['line'] !== ($tokens[$className]['line'] - 1)) { + if ($keywordTokenType === T_EXTENDS) { + $error = 'Only one interface may be specified per line in a multi-line extends declaration'; + $fix = $phpcsFile->addFixableError($error, $className, 'ExtendsInterfaceSameLine'); + } else { + $error = 'Only one interface may be specified per line in a multi-line implements declaration'; + $fix = $phpcsFile->addFixableError($error, $className, 'InterfaceSameLine'); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $className; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } else { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($className - 1), $implements); + if ($tokens[$prev]['line'] !== $tokens[$className]['line']) { + $found = 0; + } else { + $found = $tokens[$prev]['length']; + } + + $expected = ($classIndent + $this->indent); + if ($found !== $expected) { + $error = 'Expected %s spaces before interface name; %s found'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $className, 'InterfaceWrongIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($found === 0) { + $phpcsFile->fixer->addContent($prev, $padding); + } else { + $phpcsFile->fixer->replaceToken($prev, $padding); + } + } + } + }//end if + } else if ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR + || $tokens[($className - 2)]['code'] !== T_STRING + ) { + // Not part of a longer fully qualified class name. + if ($tokens[($className - 1)]['code'] === T_COMMA + || ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR + && $tokens[($className - 2)]['code'] === T_COMMA) + ) { + $error = 'Expected 1 space before "%s"; 0 found'; + $data = [$tokens[$className]['content']]; + $fix = $phpcsFile->addFixableError($error, ($nextComma + 1), 'NoSpaceBeforeName', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore(($nextComma + 1), ' '); + } + } else { + if ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR) { + $prev = ($className - 2); + } else { + $prev = ($className - 1); + } + + $last = $phpcsFile->findPrevious(T_WHITESPACE, $prev, null, true); + $content = $phpcsFile->getTokensAsString(($last + 1), ($prev - $last)); + if ($content !== ' ') { + $found = strlen($content); + + $error = 'Expected 1 space before "%s"; %s found'; + $data = [ + $tokens[$className]['content'], + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceBeforeName', $data); + if ($fix === true) { + if ($tokens[$prev]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ' '); + while ($tokens[--$prev]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($prev, ' '); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->addContent($prev, ' '); + } + } + }//end if + }//end if + }//end if + + if ($checkingImplements === true + && $tokens[($className + 1)]['code'] !== T_NS_SEPARATOR + && $tokens[($className + 1)]['code'] !== T_COMMA + ) { + if ($n !== ($classCount - 1)) { + // This is not the last class name, and the comma + // is not where we expect it to be. + if ($tokens[($className + 2)]['code'] !== $keywordTokenType) { + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $tokens[$className]['content'], + $tokens[($className + 1)]['length'], + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($className + 1), ''); + } + } + } + + $nextComma = $phpcsFile->findNext(T_COMMA, $className); + } else { + $nextComma = ($className + 1); + }//end if + }//end foreach + + }//end processOpen() + + + /** + * Processes the closing section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check that the closing brace comes right after the code body. + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + if ($prevContent !== $tokens[$stackPtr]['scope_opener'] + && $tokens[$prevContent]['line'] !== ($tokens[$closeBrace]['line'] - 1) + ) { + $error = 'The closing brace for the %s must go on the next line after the body'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'CloseBraceAfterBody', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (strpos($tokens[$prevContent]['content'], $phpcsFile->eolChar) === false) { + $phpcsFile->fixer->replaceToken($closeBrace, $phpcsFile->eolChar.$tokens[$closeBrace]['content']); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + if ($tokens[$stackPtr]['code'] !== T_ANON_CLASS) { + // Check the closing brace is on it's own line, but allow + // for comments like "//end class". + $ignoreTokens = Tokens::$phpcsCommentTokens; + $ignoreTokens[] = T_WHITESPACE; + $ignoreTokens[] = T_COMMENT; + $ignoreTokens[] = T_SEMICOLON; + $ignoreTokens[] = T_COMMA; + $nextContent = $phpcsFile->findNext($ignoreTokens, ($closeBrace + 1), null, true); + if ($tokens[$nextContent]['content'] !== $phpcsFile->eolChar + && $tokens[$nextContent]['line'] === $tokens[$closeBrace]['line'] + ) { + $type = strtolower($tokens[$stackPtr]['content']); + $error = 'Closing %s brace must be on a line by itself'; + $data = [$type]; + $phpcsFile->addError($error, $closeBrace, 'CloseBraceSameLine', $data); + } + } + + }//end processClose() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php new file mode 100644 index 000000000..efdbb4382 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php @@ -0,0 +1,185 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Tokens; + +class PropertyDeclarationSniff extends AbstractVariableSniff +{ + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'][1] === '_') { + $error = 'Property name "%s" should not be prefixed with an underscore to indicate visibility'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); + } + + // Detect multiple properties defined at the same time. Throw an error + // for this, but also only process the first property in the list so we don't + // repeat errors. + $find = Tokens::$scopeModifiers; + $find[] = T_VARIABLE; + $find[] = T_VAR; + $find[] = T_READONLY; + $find[] = T_SEMICOLON; + $find[] = T_OPEN_CURLY_BRACKET; + + $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1)); + if ($tokens[$prev]['code'] === T_VARIABLE) { + return; + } + + if ($tokens[$prev]['code'] === T_VAR) { + $error = 'The var keyword must not be used to declare a property'; + $phpcsFile->addError($error, $stackPtr, 'VarUsed'); + } + + $next = $phpcsFile->findNext([T_VARIABLE, T_SEMICOLON], ($stackPtr + 1)); + if ($next !== false && $tokens[$next]['code'] === T_VARIABLE) { + $error = 'There must not be more than one property declared per statement'; + $phpcsFile->addError($error, $stackPtr, 'Multiple'); + } + + try { + $propertyInfo = $phpcsFile->getMemberProperties($stackPtr); + if (empty($propertyInfo) === true) { + return; + } + } catch (\Exception $e) { + // Turns out not to be a property after all. + return; + } + + if ($propertyInfo['type'] !== '') { + $typeToken = $propertyInfo['type_end_token']; + $error = 'There must be 1 space after the property type declaration; %s found'; + if ($tokens[($typeToken + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($typeToken, ' '); + } + } else if ($tokens[($typeToken + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($typeToken + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$typeToken]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($typeToken + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($typeToken + 1), null, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $typeToken, 'SpacingAfterType', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($typeToken + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($typeToken, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($typeToken + 1), ' '); + } + } + } + }//end if + }//end if + + if ($propertyInfo['scope_specified'] === false) { + $error = 'Visibility must be declared on property "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data); + } + + if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_static'] === true) { + $scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1)); + $staticPtr = $phpcsFile->findPrevious(T_STATIC, ($stackPtr - 1)); + if ($scopePtr < $staticPtr) { + return; + } + + $error = 'The static declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'StaticBeforeVisibility'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($scopePtr + 1); $scopePtr < $stackPtr; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($scopePtr, ''); + $phpcsFile->fixer->addContentBefore($staticPtr, $propertyInfo['scope'].' '); + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..09d2c14a0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php @@ -0,0 +1,142 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_ELSE, + T_ELSEIF, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($parenOpener + 1), null, true); + if (in_array($tokens[$nextContent]['code'], Tokens::$commentTokens, true) === false) { + $spaceAfterOpen = 0; + if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($parenOpener + 1)]['content'], $phpcsFile->eolChar) !== false) { + $spaceAfterOpen = 'newline'; + } else { + $spaceAfterOpen = $tokens[($parenOpener + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $spaceAfterOpen); + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($parenOpener, $padding); + } else if ($spaceAfterOpen === 'newline') { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), ''); + } else { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), $padding); + } + } + } + }//end if + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($parenCloser - 1), $parenOpener, true); + if ($tokens[$prev]['line'] === $tokens[$parenCloser]['line']) { + $spaceBeforeClose = 0; + if ($tokens[($parenCloser - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = strlen(ltrim($tokens[($parenCloser - 1)]['content'], $phpcsFile->eolChar)); + } + + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $spaceBeforeClose); + + if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($parenCloser, $padding); + } else { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), $padding); + } + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100644 index 000000000..9f97684a9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ElseIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ELSE, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ELSEIF) { + $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'elseif'); + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_IF) { + $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'else if'); + $error = 'Usage of ELSE IF is discouraged; use ELSEIF instead'; + $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'NotAllowed'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, 'elseif'); + for ($i = ($stackPtr + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php new file mode 100644 index 000000000..de81c530e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php @@ -0,0 +1,396 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SwitchDeclarationSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SWITCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We can't process SWITCH statements unless we know where they start and end. + if (isset($tokens[$stackPtr]['scope_opener']) === false + || isset($tokens[$stackPtr]['scope_closer']) === false + ) { + return; + } + + $switch = $tokens[$stackPtr]; + $nextCase = $stackPtr; + $caseAlignment = ($switch['column'] + $this->indent); + + while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $switch['scope_closer'])) !== false) { + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $type = 'default'; + } else { + $type = 'case'; + } + + if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) { + $expected = strtolower($tokens[$nextCase]['content']); + $error = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $tokens[$nextCase]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'NotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($nextCase, $expected); + } + } + + if ($type === 'case' + && ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE + || $tokens[($nextCase + 1)]['content'] !== ' ') + ) { + $error = 'CASE keyword must be followed by a single space'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase'); + if ($fix === true) { + if ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent($nextCase, ' '); + } else { + $phpcsFile->fixer->replaceToken(($nextCase + 1), ' '); + } + } + } + + $opener = $tokens[$nextCase]['scope_opener']; + $nextCloser = $tokens[$nextCase]['scope_closer']; + if ($tokens[$opener]['code'] === T_COLON) { + if ($tokens[($opener - 1)]['code'] === T_WHITESPACE) { + $error = 'There must be no space before the colon in a '.strtoupper($type).' statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon'.strtoupper($type)); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($opener - 1), ''); + } + } + + for ($next = ($opener + 1); $next < $nextCloser; $next++) { + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === false + || (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] !== $tokens[$opener]['line']) + ) { + break; + } + } + + if ($tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'The '.strtoupper($type).' body must start on the line following the statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'BodyOnNextLine'.strtoupper($type)); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $padding = str_repeat(' ', ($caseAlignment + $this->indent - 1)); + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$padding); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + // Ignore trailing comments. + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[$nextCloser]['scope_condition'] === $nextCase) { + // Only need to check some things once, even if the + // closer is shared between multiple case statements, or even + // the default case. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCloser - 1), $nextCase, true); + if ($tokens[$prev]['line'] === $tokens[$nextCloser]['line']) { + $error = 'Terminating statement must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakNotNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewLine($prev); + $phpcsFile->fixer->replaceToken($nextCloser, trim($tokens[$nextCloser]['content'])); + } + } else { + $diff = ($tokens[$nextCase]['column'] + $this->indent - $tokens[$nextCloser]['column']); + if ($diff !== 0) { + $error = 'Terminating statement must be indented to the same level as the CASE body'; + $fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakIndent'); + if ($fix === true) { + if ($diff > 0) { + $phpcsFile->fixer->addContentBefore($nextCloser, str_repeat(' ', $diff)); + } else { + $phpcsFile->fixer->substrToken(($nextCloser - 1), 0, $diff); + } + } + } + }//end if + }//end if + } else { + $error = strtoupper($type).' statements must be defined using a colon'; + $phpcsFile->addError($error, $nextCase, 'WrongOpener'.$type); + }//end if + + // We only want cases from here on in. + if ($type !== 'case') { + continue; + } + + $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), $nextCloser, true); + + if ($tokens[$nextCode]['code'] !== T_CASE && $tokens[$nextCode]['code'] !== T_DEFAULT) { + // This case statement has content. If the next case or default comes + // before the closer, it means we don't have an obvious terminating + // statement and need to make some more effort to find one. If we + // don't, we do need a comment. + $nextCode = $this->findNextCase($phpcsFile, ($opener + 1), $nextCloser); + if ($nextCode !== false) { + $prevCode = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCode - 1), $nextCase, true); + if (isset(Tokens::$commentTokens[$tokens[$prevCode]['code']]) === false + && $this->findNestedTerminator($phpcsFile, ($opener + 1), $nextCode) === false + ) { + $error = 'There must be a comment when fall-through is intentional in a non-empty case body'; + $phpcsFile->addError($error, $nextCase, 'TerminatingComment'); + } + } + } + }//end while + + }//end process() + + + /** + * Find the next CASE or DEFAULT statement from a point in the file. + * + * Note that nested switches are ignored. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position to start looking at. + * @param int $end The position to stop looking at. + * + * @return int|false + */ + private function findNextCase($phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + while (($stackPtr = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], $stackPtr, $end)) !== false) { + // Skip nested SWITCH statements; they are handled on their own. + if ($tokens[$stackPtr]['code'] === T_SWITCH) { + $stackPtr = $tokens[$stackPtr]['scope_closer']; + continue; + } + + break; + } + + return $stackPtr; + + }//end findNextCase() + + + /** + * Returns the position of the nested terminating statement. + * + * Returns false if no terminating statement was found. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position to start looking at. + * @param int $end The position to stop looking at. + * + * @return int|false + */ + private function findNestedTerminator($phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + + $lastToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($end - 1), $stackPtr, true); + if ($lastToken === false) { + return false; + } + + if ($tokens[$lastToken]['code'] === T_CLOSE_CURLY_BRACKET) { + // We found a closing curly bracket and want to check if its block + // belongs to a SWITCH, IF, ELSEIF or ELSE, TRY, CATCH OR FINALLY clause. + // If yes, we continue searching for a terminating statement within that + // block. Note that we have to make sure that every block of + // the entire if/else/switch statement has a terminating statement. + // For a try/catch/finally statement, either the finally block has + // to have a terminating statement or every try/catch block has to have one. + $currentCloser = $lastToken; + $hasElseBlock = false; + $hasCatchWithoutTerminator = false; + do { + $scopeOpener = $tokens[$currentCloser]['scope_opener']; + $scopeCloser = $tokens[$currentCloser]['scope_closer']; + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($scopeOpener - 1), $stackPtr, true); + if ($prevToken === false) { + return false; + } + + // SWITCH, IF, ELSEIF, CATCH clauses possess a condition we have to account for. + if ($tokens[$prevToken]['code'] === T_CLOSE_PARENTHESIS) { + $prevToken = $tokens[$prevToken]['parenthesis_owner']; + } + + if ($tokens[$prevToken]['code'] === T_IF) { + // If we have not encountered an ELSE clause by now, we cannot + // be sure that the whole statement terminates in every case. + if ($hasElseBlock === false) { + return false; + } + + return $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + } else if ($tokens[$prevToken]['code'] === T_ELSEIF + || $tokens[$prevToken]['code'] === T_ELSE + ) { + // If we find a terminating statement within this block, + // we continue with the previous ELSEIF or IF clause. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator === false) { + return false; + } + + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + if ($tokens[$prevToken]['code'] === T_ELSE) { + $hasElseBlock = true; + } + } else if ($tokens[$prevToken]['code'] === T_FINALLY) { + // If we find a terminating statement within this block, + // the whole try/catch/finally statement is covered. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator !== false) { + return $hasTerminator; + } + + // Otherwise, we continue with the previous TRY or CATCH clause. + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + } else if ($tokens[$prevToken]['code'] === T_TRY) { + // If we've seen CATCH blocks without terminator statement and + // have not seen a FINALLY *with* a terminator statement, we + // don't even need to bother checking the TRY. + if ($hasCatchWithoutTerminator === true) { + return false; + } + + return $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + } else if ($tokens[$prevToken]['code'] === T_CATCH) { + // Keep track of seen catch statements without terminating statement, + // but don't bow out yet as there may still be a FINALLY clause + // with a terminating statement before the CATCH. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator === false) { + $hasCatchWithoutTerminator = true; + } + + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + } else if ($tokens[$prevToken]['code'] === T_SWITCH) { + $hasDefaultBlock = false; + $endOfSwitch = $tokens[$prevToken]['scope_closer']; + $nextCase = $prevToken; + + // We look for a terminating statement within every blocks. + while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $endOfSwitch)) !== false) { + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $hasDefaultBlock = true; + } + + $opener = $tokens[$nextCase]['scope_opener']; + + $nextCode = $phpcsFile->findNext(Tokens::$emptyTokens, ($opener + 1), $endOfSwitch, true); + if ($tokens[$nextCode]['code'] === T_CASE || $tokens[$nextCode]['code'] === T_DEFAULT) { + // This case statement has no content, so skip it. + continue; + } + + $endOfCase = $this->findNextCase($phpcsFile, ($opener + 1), $endOfSwitch); + if ($endOfCase === false) { + $endOfCase = $endOfSwitch; + } + + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($opener + 1), $endOfCase); + if ($hasTerminator === false) { + return false; + } + }//end while + + // If we have not encountered a DEFAULT block by now, we cannot + // be sure that the whole statement terminates in every case. + if ($hasDefaultBlock === false) { + return false; + } + + return $hasTerminator; + } else { + return false; + }//end if + } while ($currentCloser !== false && $tokens[$currentCloser]['code'] === T_CLOSE_CURLY_BRACKET); + + return true; + } else if ($tokens[$lastToken]['code'] === T_SEMICOLON) { + // We found the last statement of the CASE. Now we want to + // check whether it is a terminating one. + $terminators = [ + T_RETURN => T_RETURN, + T_BREAK => T_BREAK, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ]; + + $terminator = $phpcsFile->findStartOfStatement(($lastToken - 1)); + if (isset($terminators[$tokens[$terminator]['code']]) === true) { + return $terminator; + } + }//end if + + return false; + + }//end findNestedTerminator() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php new file mode 100644 index 000000000..39834b386 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClosingTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this file only contains PHP code. + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] === T_INLINE_HTML + && trim($tokens[$i]['content']) !== '' + ) { + return $phpcsFile->numTokens; + } + } + + // Find the last non-empty token. + for ($last = ($phpcsFile->numTokens - 1); $last > 0; $last--) { + if (trim($tokens[$last]['content']) !== '') { + break; + } + } + + if ($tokens[$last]['code'] === T_CLOSE_TAG) { + $error = 'A closing tag is not permitted at the end of a PHP file'; + $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($last - 1), null, true); + if ($tokens[$prev]['code'] !== T_SEMICOLON + && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET + && $tokens[$prev]['code'] !== T_OPEN_TAG + ) { + $phpcsFile->fixer->addContent($prev, ';'); + } + + $phpcsFile->fixer->endChangeset(); + } + + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'no'); + }//end if + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php new file mode 100644 index 000000000..aed461f83 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNewlineSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($phpcsFile->findNext(T_INLINE_HTML, ($stackPtr + 1)) !== false) { + return ($phpcsFile->numTokens + 1); + } + + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $lastToken = ($phpcsFile->numTokens - 1); + + if ($tokens[$lastToken]['content'] === '') { + $lastToken--; + } + + // Hard-coding the expected \n in this sniff as it is PSR-2 specific and + // PSR-2 enforces the use of unix style newlines. + if (substr($tokens[$lastToken]['content'], -1) !== "\n") { + $error = 'Expected 1 newline at end of file; 0 found'; + $fix = $phpcsFile->addFixableError($error, $lastToken, 'NoneFound'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($lastToken); + } + + $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', '0'); + return ($phpcsFile->numTokens + 1); + } + + // Go looking for the last non-empty line. + $lastLine = $tokens[$lastToken]['line']; + if ($tokens[$lastToken]['code'] === T_WHITESPACE + || $tokens[$lastToken]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $lastCode = $phpcsFile->findPrevious([T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], ($lastToken - 1), null, true); + } else { + $lastCode = $lastToken; + } + + $lastCodeLine = $tokens[$lastCode]['line']; + $blankLines = ($lastLine - $lastCodeLine + 1); + $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', $blankLines); + + if ($blankLines > 1) { + $error = 'Expected 1 blank line at end of file; %s found'; + $data = [$blankLines]; + $fix = $phpcsFile->addFixableError($error, $lastCode, 'TooMany', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($lastCode, rtrim($tokens[$lastCode]['content'])); + for ($i = ($lastCode + 1); $i < $lastToken; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($lastToken, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + // Skip the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php new file mode 100644 index 000000000..406f27948 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionCallSignatureSniff as PEARFunctionCallSignatureSniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallSignatureSniff extends PEARFunctionCallSignatureSniff +{ + + /** + * If TRUE, multiple arguments can be defined per line in a multi-line call. + * + * @var boolean + */ + public $allowMultipleArguments = false; + + + /** + * Processes single-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + // If the first argument is on a new line, this is a multi-line + // function call, even if there is only one argument. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + return true; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $end = $phpcsFile->findEndOfStatement(($openBracket + 1), [T_COLON]); + while ($tokens[$end]['code'] === T_COMMA) { + // If the next bit of code is not on the same line, this is a + // multi-line function call. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next === false) { + return false; + } + + if ($tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + $end = $phpcsFile->findEndOfStatement($next, [T_COLON]); + } + + // We've reached the last argument, so see if the next content + // (should be the close bracket) is also on the same line. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + return false; + + }//end isMultiLineCall() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php new file mode 100644 index 000000000..1e11f02f2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + $found = ($tokens[$closeBrace]['line'] - $tokens[$prevContent]['line'] - 1); + + if ($found < 0) { + // Brace isn't on a new line, so not handled by us. + return; + } + + if ($found === 0) { + // All is good. + return; + } + + $error = 'Function closing brace must go on the next line following the body; found %s blank lines before brace'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeClose', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + if ($tokens[$i]['line'] === $tokens[$prevContent]['line']) { + continue; + } + + // Don't remove any indentation before the brace. + if ($tokens[$i]['line'] === $tokens[$closeBrace]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php new file mode 100644 index 000000000..d23b8bee2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MethodDeclarationSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + if ($methodName[0] === '_' && isset($methodName[1]) === true && $methodName[1] !== '_') { + $error = 'Method name "%s" should not be prefixed with an underscore to indicate visibility'; + $data = [$methodName]; + $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); + } + + $visibility = 0; + $static = 0; + $abstract = 0; + $final = 0; + + $find = (Tokens::$methodPrefixes + Tokens::$emptyTokens); + $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + + $prefix = $stackPtr; + while (($prefix = $phpcsFile->findPrevious(Tokens::$methodPrefixes, ($prefix - 1), $prev)) !== false) { + switch ($tokens[$prefix]['code']) { + case T_STATIC: + $static = $prefix; + break; + case T_ABSTRACT: + $abstract = $prefix; + break; + case T_FINAL: + $final = $prefix; + break; + default: + $visibility = $prefix; + break; + } + } + + $fixes = []; + + if ($visibility !== 0 && $final > $visibility) { + $error = 'The final declaration must precede the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $final, 'FinalAfterVisibility'); + if ($fix === true) { + $fixes[$final] = ''; + $fixes[($final + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] = 'final '.$fixes[$visibility]; + } else { + $fixes[$visibility] = 'final '.$tokens[$visibility]['content']; + } + } + } + + if ($visibility !== 0 && $abstract > $visibility) { + $error = 'The abstract declaration must precede the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $abstract, 'AbstractAfterVisibility'); + if ($fix === true) { + $fixes[$abstract] = ''; + $fixes[($abstract + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] = 'abstract '.$fixes[$visibility]; + } else { + $fixes[$visibility] = 'abstract '.$tokens[$visibility]['content']; + } + } + } + + if ($static !== 0 && $static < $visibility) { + $error = 'The static declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $static, 'StaticBeforeVisibility'); + if ($fix === true) { + $fixes[$static] = ''; + $fixes[($static + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] .= ' static'; + } else { + $fixes[$visibility] = $tokens[$visibility]['content'].' static'; + } + } + } + + // Batch all the fixes together to reduce the possibility of conflicts. + if (empty($fixes) === false) { + $phpcsFile->fixer->beginChangeset(); + foreach ($fixes as $stackPtr => $content) { + $phpcsFile->fixer->replaceToken($stackPtr, $content); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php new file mode 100644 index 000000000..bf37af09b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php @@ -0,0 +1,100 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NamespaceDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NAMESPACE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_NS_SEPARATOR) { + // Namespace keyword as operator. Not a declaration. + return; + } + + $end = $phpcsFile->findEndOfStatement($stackPtr); + for ($i = ($end + 1); $i < ($phpcsFile->numTokens - 1); $i++) { + if ($tokens[$i]['line'] === $tokens[$end]['line']) { + continue; + } + + break; + } + + // The $i var now points to the first token on the line after the + // namespace declaration, which must be a blank line. + $next = $phpcsFile->findNext(T_WHITESPACE, $i, $phpcsFile->numTokens, true); + if ($next === false) { + return; + } + + $diff = ($tokens[$next]['line'] - $tokens[$i]['line']); + if ($diff === 1) { + return; + } + + if ($diff < 0) { + $diff = 0; + } + + $error = 'There must be one blank line after the namespace declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BlankLineAfter'); + + if ($fix === true) { + if ($diff === 0) { + $phpcsFile->fixer->addNewlineBefore($i); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($x = $i; $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($i); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php new file mode 100644 index 000000000..aba9caa71 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php @@ -0,0 +1,297 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->shouldIgnoreUse($phpcsFile, $stackPtr) === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // One space after the use keyword. + if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + $error = 'There must be a single space after the USE keyword'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterUse'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + + // Only one USE declaration allowed per statement. + $next = $phpcsFile->findNext([T_COMMA, T_SEMICOLON, T_OPEN_USE_GROUP, T_CLOSE_TAG], ($stackPtr + 1)); + if ($next !== false + && $tokens[$next]['code'] !== T_SEMICOLON + && $tokens[$next]['code'] !== T_CLOSE_TAG + ) { + $error = 'There must be one USE keyword per declaration'; + + if ($tokens[$next]['code'] === T_COMMA) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MultipleDeclarations'); + if ($fix === true) { + switch ($tokens[($stackPtr + 2)]['content']) { + case 'const': + $baseUse = 'use const'; + break; + case 'function': + $baseUse = 'use function'; + break; + default: + $baseUse = 'use'; + } + + if ($tokens[($next + 1)]['code'] !== T_WHITESPACE) { + $baseUse .= ' '; + } + + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar.$baseUse); + } + } else { + $closingCurly = $phpcsFile->findNext(T_CLOSE_USE_GROUP, ($next + 1)); + if ($closingCurly === false) { + // Parse error or live coding. Not auto-fixable. + $phpcsFile->addError($error, $stackPtr, 'MultipleDeclarations'); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MultipleDeclarations'); + if ($fix === true) { + $baseUse = rtrim($phpcsFile->getTokensAsString($stackPtr, ($next - $stackPtr))); + $lastNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingCurly - 1), null, true); + + $phpcsFile->fixer->beginChangeset(); + + // Remove base use statement. + for ($i = $stackPtr; $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (preg_match('`^[\r\n]+$`', $tokens[($next + 1)]['content']) === 1) { + $phpcsFile->fixer->replaceToken(($next + 1), ''); + } + + // Convert grouped use statements into full use statements. + do { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + if ($next === false) { + // Group use statement with trailing comma after last item. + break; + } + + $nonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), null, true); + for ($i = ($nonWhitespace + 1); $i < $next; $i++) { + if (preg_match('`^[\r\n]+$`', $tokens[$i]['content']) === 1) { + // Preserve new lines. + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + if ($tokens[$next]['content'] === 'const' || $tokens[$next]['content'] === 'function') { + $phpcsFile->fixer->addContentBefore($next, 'use '); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + $phpcsFile->fixer->addContentBefore($next, str_replace('use ', '', $baseUse)); + } else { + $phpcsFile->fixer->addContentBefore($next, $baseUse); + } + + $next = $phpcsFile->findNext(T_COMMA, ($next + 1), $closingCurly); + if ($next !== false) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['line'] === $tokens[$next]['line']) { + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($nextNonEmpty - 1), $next, true); + if ($prevNonWhitespace === $next) { + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar); + } else { + $phpcsFile->fixer->replaceToken($next, ';'); + $phpcsFile->fixer->addNewline($prevNonWhitespace); + } + } else { + // Last item with trailing comma or next item already on new line. + $phpcsFile->fixer->replaceToken($next, ';'); + } + } else { + // Last item without trailing comma. + $phpcsFile->fixer->addContent($lastNonWhitespace, ';'); + } + } while ($next !== false); + + // Remove closing curly,semi-colon and any whitespace between last child and closing curly. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($closingCurly + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_SEMICOLON) { + // Parse error, forgotten semi-colon. + $next = $closingCurly; + } + + for ($i = ($lastNonWhitespace + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Make sure this USE comes after the first namespace declaration. + $prev = $phpcsFile->findPrevious(T_NAMESPACE, ($stackPtr - 1)); + if ($prev === false) { + $next = $phpcsFile->findNext(T_NAMESPACE, ($stackPtr + 1)); + if ($next !== false) { + $error = 'USE declarations must go after the namespace declaration'; + $phpcsFile->addError($error, $stackPtr, 'UseBeforeNamespace'); + } + } + + // Only interested in the last USE statement from here onwards. + $nextUse = $phpcsFile->findNext(T_USE, ($stackPtr + 1)); + while ($this->shouldIgnoreUse($phpcsFile, $nextUse) === true) { + $nextUse = $phpcsFile->findNext(T_USE, ($nextUse + 1)); + if ($nextUse === false) { + break; + } + } + + if ($nextUse !== false) { + return; + } + + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_USE_GROUP, T_CLOSE_TAG], ($stackPtr + 1)); + if ($end === false) { + return; + } + + if ($tokens[$end]['code'] === T_CLOSE_USE_GROUP) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $end = $nextNonEmpty; + } + } + + // Find either the start of the next line or the beginning of the next statement, + // whichever comes first. + for ($end = ++$end; $end < $phpcsFile->numTokens; $end++) { + if (isset(Tokens::$emptyTokens[$tokens[$end]['code']]) === false) { + break; + } + + if ($tokens[$end]['column'] === 1) { + // Reached the next line. + break; + } + } + + --$end; + + if (($tokens[$end]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$end]['code']]) === true) + && substr($tokens[$end]['content'], 0, 2) === '/*' + && substr($tokens[$end]['content'], -2) !== '*/' + ) { + // Multi-line block comments are not allowed as trailing comment after a use statement. + --$end; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true); + + if ($next === false || $tokens[$next]['code'] === T_CLOSE_TAG) { + return; + } + + $diff = ($tokens[$next]['line'] - $tokens[$end]['line'] - 1); + if ($diff !== 1) { + if ($diff < 0) { + $diff = 0; + } + + $error = 'There must be one blank line after the last USE statement; %s found;'; + $data = [$diff]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterLastUse', $data); + if ($fix === true) { + if ($diff === 0) { + $phpcsFile->fixer->addNewline($end); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($end + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($end); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end process() + + + /** + * Check if this use statement is part of the namespace block. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return bool + */ + private function shouldIgnoreUse($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore USE keywords inside closures and during live coding. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return true; + } + + // Ignore USE keywords for traits. + if ($phpcsFile->hasCondition($stackPtr, [T_CLASS, T_TRAIT, T_ENUM]) === true) { + return true; + } + + return false; + + }//end shouldIgnoreUse() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc new file mode 100644 index 000000000..13e596e17 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc @@ -0,0 +1,241 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +class A extends B + implements C +{ +} + +class C2 +{ + +} // phpcs:ignore Standard.Category.Sniff + +interface I1 extends + Foo +{ +} + +interface I2 extends + Bar +{ +} + +interface I3 extends + Foo, + Bar +{ +} + +class C1 extends + Foo +{ +} + +class C2 extends + Bar +{ +} + +class C3 extends Foo implements + Bar +{ +} + +class C4 extends Foo implements + Bar +{ +} + +class C5 extends Foo implements + Bar, + Baz +{ +} + +class C6 extends \Foo\Bar implements + \Baz\Bar +{ +} + +interface I4 extends + \Baz + \Bar +{ +} + +interface I5 extends /* comment */ + \Foo\Bar +{ +} + +interface I6 extends // comment + \Foo\Bar +{ +} + +class C7 extends // comment + \Foo\Bar implements \Baz\Bar +{ +} + +class +C8 +{ +} + +foo(new class { +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..3ee394e78 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed @@ -0,0 +1,234 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +class A extends B implements C +{ +} + +class C2 +{ + +} // phpcs:ignore Standard.Category.Sniff + +interface I1 extends + Foo +{ +} + +interface I2 extends + Bar +{ +} + +interface I3 extends + Foo, + Bar +{ +} + +class C1 extends Foo +{ +} + +class C2 extends Bar +{ +} + +class C3 extends Foo implements + Bar +{ +} + +class C4 extends Foo implements + Bar +{ +} + +class C5 extends Foo implements + Bar, + Baz +{ +} + +class C6 extends \Foo\Bar implements + \Baz\Bar +{ +} + +interface I4 extends + \Baz\Bar +{ +} + +interface I5 extends /* comment */ + \Foo\Bar +{ +} + +interface I6 extends // comment + \Foo\Bar +{ +} + +class C7 extends \Foo\Bar implements \Baz\Bar // comment +{ +} + +class C8 +{ +} + +foo(new class { +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php new file mode 100644 index 000000000..635ac710b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 7 => 3, + 12 => 1, + 13 => 1, + 17 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 1, + 25 => 1, + 27 => 2, + 34 => 1, + 35 => 2, + 44 => 1, + 45 => 1, + 63 => 1, + 95 => 1, + 116 => 1, + 118 => 1, + 119 => 1, + 124 => 1, + 130 => 2, + 131 => 1, + 158 => 1, + 168 => 1, + 178 => 1, + 179 => 1, + 184 => 1, + 189 => 1, + 194 => 1, + 204 => 1, + 205 => 1, + 210 => 1, + 215 => 2, + 216 => 1, + 231 => 2, + 235 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc new file mode 100644 index 000000000..33bec44e7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class PropertyDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 9 => 2, + 10 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 23 => 1, + 38 => 1, + 41 => 1, + 42 => 1, + 50 => 2, + 51 => 1, + 55 => 1, + 56 => 1, + 61 => 1, + 62 => 1, + 68 => 1, + 69 => 1, + 71 => 1, + 72 => 1, + 76 => 1, + 80 => 1, + 82 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 13 => 1, + 14 => 1, + 15 => 1, + 53 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc new file mode 100644 index 000000000..542ab3cf2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,81 @@ + $that) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 + +$binary = b"binary string"; + +if ($expr1 + && $expr2 ) { +} + +if ($expr1 + && $expr2 /* comment */ ) { +} + +if ($expr1 + && $expr2 + /* comment */ ) { +} + +$r = match ($x) {}; +$r = match ( $x ) {}; + +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 1 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 1 +$r = match ($x) {}; +$r = match ( $x ) {}; +$r = match ( $x ) {}; +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..a29534bee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,80 @@ + $that ) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 + +$binary = b"binary string"; + +if ($expr1 + && $expr2) { +} + +if ($expr1 + && $expr2 /* comment */) { +} + +if ($expr1 + && $expr2 + /* comment */) { +} + +$r = match ($x) {}; +$r = match ($x) {}; + +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 1 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 1 +$r = match ( $x ) {}; +$r = match ( $x ) {}; +$r = match ( $x ) {}; +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php new file mode 100644 index 000000000..35d5e5150 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 14 => 2, + 26 => 2, + 27 => 2, + 31 => 1, + 51 => 2, + 53 => 2, + 60 => 1, + 64 => 1, + 69 => 1, + 73 => 2, + 77 => 2, + 79 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc new file mode 100644 index 000000000..778659c82 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..4a7bfdc27 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php new file mode 100644 index 000000000..935205b40 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ElseIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc new file mode 100644 index 000000000..2ca60a93e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc @@ -0,0 +1,598 @@ + 0) { + return 0; + } else { + return 1; + } + case 2: + return 2; +} + +// ERROR: No else clause +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } + case 2: + return 2; +} + +// OK: No fall-through present +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } +} + +// ERROR: No else clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } else { + break; + } + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause +switch ($foo) { + case 1: + if ($bar > 0) { + $offset = 0; + } else { + break; + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + continue; + } else { + if ($foo > $bar) { + $offset = 0; + } else { + break; + } + } + case 2: + return 2; +} + +switch ($sContext) +{ + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +$foo = $foo ? + function () { + switch ($a) { + case 'a': + break; + } + } : + null; + +switch ($foo) { +case Foo::INTERFACE: + echo '1'; + return self::INTERFACE; +case Foo::TRAIT: +case Foo::ARRAY: + echo '1'; + return self::VALUE; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + return 3; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + default: + $a = 1; + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + throw new \Exception(); + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + // phpcs:ignore + case 2: + return 1; + case 3: + return 2; +} + +// Issue 3352. +switch ( $test ) { + case 2: // comment followed by empty line + + break; + + case 3: /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments. */ + + + + break; + + case 4: /** inline docblock */ + + + + break; + + case 5: /* checking how it handles */ /* two trailing comments */ + + break; + + case 6: + // Comment as first content of the body. + + break; + + case 7: + /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments at start of body. */ + + break; + + case 8: + /** inline docblock */ + + break; +} + +// Handle comments correctly. +switch ($foo) { + case 1: + if ($bar > 0) { + doSomething(); + } + // Comment + else { + return 1; + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + if ($bar > 0) /*comment*/ { + return doSomething(); + } + else { + return 1; + } + case 2: + return 2; +} + +// Issue #3297. +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + doSomething(); + } finally { + return true; + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) /*comment*/ { + return true; + } + // Comment + catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } finally { + return true; + } catch (AnotherException $e) { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + return false; + } finally { + doSomething(); + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no finally. Any exception still uncaught will terminate the case anyhow, so we're good. +switch ( $a ) { + case 1: + try { + return false; + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no catch +switch ( $a ) { + case 1: + try { + return true; + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// All okay, try-catch nested in if. +switch ( $a ) { + case 1: + if ($a) { + try { + return true; // Comment. + } catch (MyException $e) { + throw new Exception($e->getMessage()); + } + } else { + return true; + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. Try does not have a terminating statement. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } catch (Exception $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Issue 3550 - comment after terminating statement. +switch (rand()) { + case 1: + if (rand() === 1) { + break; + } else { + break; // comment + } + default: + break; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..bbc8b7c48 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed @@ -0,0 +1,593 @@ + 0) { + return 0; + } else { + return 1; + } + case 2: + return 2; +} + +// ERROR: No else clause +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } + case 2: + return 2; +} + +// OK: No fall-through present +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } +} + +// ERROR: No else clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } else { + break; + } + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause +switch ($foo) { + case 1: + if ($bar > 0) { + $offset = 0; + } else { + break; + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + continue; + } else { + if ($foo > $bar) { + $offset = 0; + } else { + break; + } + } + case 2: + return 2; +} + +switch ($sContext) +{ + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +$foo = $foo ? + function () { + switch ($a) { + case 'a': + break; + } + } : + null; + +switch ($foo) { +case Foo::INTERFACE: + echo '1'; + return self::INTERFACE; +case Foo::TRAIT: +case Foo::ARRAY: + echo '1'; + return self::VALUE; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + return 3; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + default: + $a = 1; + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + throw new \Exception(); + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + // phpcs:ignore + case 2: + return 1; + case 3: + return 2; +} + +// Issue 3352. +switch ( $test ) { + case 2: // comment followed by empty line + break; + + case 3: /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments. */ + break; + + case 4: /** inline docblock */ + break; + + case 5: /* checking how it handles */ /* two trailing comments */ + break; + + case 6: + // Comment as first content of the body. + + break; + + case 7: + /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments at start of body. */ + + break; + + case 8: + /** inline docblock */ + + break; +} + +// Handle comments correctly. +switch ($foo) { + case 1: + if ($bar > 0) { + doSomething(); + } + // Comment + else { + return 1; + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + if ($bar > 0) /*comment*/ { + return doSomething(); + } + else { + return 1; + } + case 2: + return 2; +} + +// Issue #3297. +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + doSomething(); + } finally { + return true; + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) /*comment*/ { + return true; + } + // Comment + catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } finally { + return true; + } catch (AnotherException $e) { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + return false; + } finally { + doSomething(); + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no finally. Any exception still uncaught will terminate the case anyhow, so we're good. +switch ( $a ) { + case 1: + try { + return false; + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no catch +switch ( $a ) { + case 1: + try { + return true; + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// All okay, try-catch nested in if. +switch ( $a ) { + case 1: + if ($a) { + try { + return true; // Comment. + } catch (MyException $e) { + throw new Exception($e->getMessage()); + } + } else { + return true; + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. Try does not have a terminating statement. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } catch (Exception $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Issue 3550 - comment after terminating statement. +switch (rand()) { + case 1: + if (rand() === 1) { + break; + } else { + break; // comment + } + default: + break; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php new file mode 100644 index 000000000..0cd946d88 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SwitchDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 23 => 1, + 29 => 1, + 33 => 1, + 37 => 2, + 108 => 2, + 109 => 1, + 111 => 1, + 113 => 2, + 114 => 1, + 128 => 1, + 141 => 1, + 172 => 1, + 194 => 1, + 224 => 1, + 236 => 1, + 260 => 1, + 300 => 1, + 311 => 1, + 346 => 1, + 350 => 1, + 356 => 1, + 362 => 1, + 384 => 1, + 528 => 1, + 541 => 1, + 558 => 1, + 575 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc new file mode 100644 index 000000000..738e70e9b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc @@ -0,0 +1,12 @@ + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed new file mode 100644 index 000000000..f70b9ebad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed @@ -0,0 +1,12 @@ + + +
    + +
    \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc new file mode 100644 index 000000000..d6a861750 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc @@ -0,0 +1,7 @@ + + +A: +B: +C: \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc new file mode 100644 index 000000000..dd103cde3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc @@ -0,0 +1 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed new file mode 100644 index 000000000..1058f1f37 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed @@ -0,0 +1 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed new file mode 100644 index 000000000..93d55fbdc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed new file mode 100644 index 000000000..534574d44 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed new file mode 100644 index 000000000..68e7d8ce0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed @@ -0,0 +1,5 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingTagUnitTest.1.inc': + return [11 => 1]; + + case 'ClosingTagUnitTest.4.inc': + case 'ClosingTagUnitTest.5.inc': + return [1 => 1]; + + case 'ClosingTagUnitTest.6.inc': + case 'ClosingTagUnitTest.7.inc': + return [5 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc new file mode 100644 index 000000000..ca2a7493a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed new file mode 100644 index 000000000..d3c19feeb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed @@ -0,0 +1 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc new file mode 100644 index 000000000..fa2f476a9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc @@ -0,0 +1,5 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc new file mode 100644 index 000000000..1254e4a55 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc @@ -0,0 +1,2 @@ + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc new file mode 100644 index 000000000..c3a59b672 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc @@ -0,0 +1,6 @@ + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EndFileNewlineUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'EndFileNewlineUnitTest.1.inc': + case 'EndFileNewlineUnitTest.3.inc': + case 'EndFileNewlineUnitTest.6.inc': + case 'EndFileNewlineUnitTest.7.inc': + case 'EndFileNewlineUnitTest.9.inc': + case 'EndFileNewlineUnitTest.10.inc': + return [2 => 1]; + case 'EndFileNewlineUnitTest.11.inc': + case 'EndFileNewlineUnitTest.12.inc': + case 'EndFileNewlineUnitTest.13.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc new file mode 100644 index 000000000..1ca477d05 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc @@ -0,0 +1,267 @@ +get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}, array( + '1', + '2', + '3', +)); + +// error +somefunction2($foo, $bar, [ + // ... + ], +$baz); + +// ok +somefunction3(// ... + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction4(' + this should not + give an error + because it\'s actually + one line call + with multi-line string +'); + +// ok +somefunction5("hey, +multi-line string with some +extra args", $foo, 12); + +// error +somefunction6(' + but args in a new line + are not ok… + ', + $foo +); + +$this->setFoo(true + ? 1 + : 2, false, array( + 'value', + 'more')); + +$this->setFoo('some' + . 'long' + . 'text', 'string'); + +foo(bar(), $a); +foo();bar(); + +foo( + true +); + +myFunction(<< function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +$this->listeners[] = $events->getSharedManager()->attach( + 'Zend\Mvc\Application', MvcEvent::EVENT_DISPATCH, [$this, 'selectLayout'], 100 +); + +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 1 +foo('Testing + multiline text' + ); + +foo('Testing + multiline text: ' // . $text + ); + +foo('Testing + multiline text: ' /* . $text */ + ); + +foo('Testing + multiline text: ' /* . $text */ + // . $other_text + ); + +foo('Testing + multiline text: ' /* + . $text +// . $text2 + */ + ); +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 0 + +foo('Testing + multiline text' +); + +foo('Testing + multiline text' + ); + +foo('Testing + multiline text' // hello +); + +foo('Testing + multiline text' /* hello */ +); + +foo('Testing + multiline text' + // hello +); + +foo('Testing + multiline text' + /* hello */ +); + +$var = foo('Testing + multiline' + // hi + ) + foo('Testing + multiline' + // hi + ) +; + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a', 'b', 'c' + ); + } +} + +$x = $var('y', + 'x'); + +$obj->{$x}(1, +2); + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)('c', + 'd'); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + )); + +return trim(preg_replace_callback( +// sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) +// /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ +sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), +function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; +}, +$search +)); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); + +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments true +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed new file mode 100644 index 000000000..dc383ed2a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed @@ -0,0 +1,283 @@ +get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}, array( + '1', + '2', + '3', +)); + +// error +somefunction2( + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction3(// ... + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction4(' + this should not + give an error + because it\'s actually + one line call + with multi-line string +'); + +// ok +somefunction5("hey, +multi-line string with some +extra args", $foo, 12); + +// error +somefunction6( + ' + but args in a new line + are not ok… + ', + $foo +); + +$this->setFoo(true + ? 1 + : 2, false, array( + 'value', + 'more')); + +$this->setFoo('some' + . 'long' + . 'text', 'string'); + +foo(bar(), $a); +foo();bar(); + +foo( + true +); + +myFunction(<< function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, + function ($x) { + return $x; + } +); + +$this->listeners[] = $events->getSharedManager()->attach( + 'Zend\Mvc\Application', + MvcEvent::EVENT_DISPATCH, + [$this, 'selectLayout'], + 100 +); + +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 1 +foo('Testing + multiline text' ); + +foo('Testing + multiline text: ' ); // . $text + + +foo('Testing + multiline text: ' /* . $text */ ); + +foo('Testing + multiline text: ' /* . $text */ ); + // . $other_text + + +foo('Testing + multiline text: ' /* + . $text +// . $text2 + */ ); +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 0 + +foo('Testing + multiline text'); + +foo('Testing + multiline text'); + +foo('Testing + multiline text'); // hello + + +foo('Testing + multiline text' /* hello */); + +foo('Testing + multiline text'); + // hello + + +foo('Testing + multiline text' + /* hello */); + +$var = foo('Testing + multiline') + // hi + + foo('Testing + multiline'); + // hi + + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a', + 'b', + 'c' + ); + } +} + +$x = $var( + 'y', + 'x' +); + +$obj->{$x}( + 1, + 2 +); + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a', + 'b' +)( + 'c', + 'd' +); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search +)); + +return trim(preg_replace_callback( +// sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) +// /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search +)); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments true +array_fill_keys( + keys: range( + 1, + 12, + ), value: true, +); +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php new file mode 100644 index 000000000..1d8782589 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php @@ -0,0 +1,94 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCallSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 18 => 3, + 21 => 1, + 48 => 1, + 87 => 1, + 90 => 1, + 91 => 1, + 103 => 1, + 111 => 1, + 117 => 4, + 123 => 1, + 127 => 1, + 131 => 1, + 136 => 1, + 143 => 1, + 148 => 1, + 152 => 1, + 156 => 1, + 160 => 1, + 165 => 1, + 170 => 1, + 175 => 1, + 178 => 2, + 186 => 1, + 187 => 1, + 194 => 3, + 199 => 1, + 200 => 2, + 202 => 1, + 203 => 1, + 210 => 2, + 211 => 1, + 212 => 2, + 217 => 1, + 218 => 1, + 227 => 1, + 228 => 1, + 233 => 1, + 234 => 1, + 242 => 1, + 243 => 1, + 256 => 1, + 257 => 1, + 258 => 1, + 263 => 1, + 264 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc new file mode 100644 index 000000000..7bf667e6e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 16 => 1, + 23 => 1, + 40 => 1, + 47 => 1, + 63 => 1, + 70 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc new file mode 100644 index 000000000..096b44bc8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MethodDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 11 => 1, + 13 => 1, + 15 => 3, + 24 => 1, + 34 => 1, + 36 => 1, + 38 => 1, + 40 => 3, + 50 => 1, + 52 => 1, + 54 => 1, + 56 => 3, + 63 => 2, + 73 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 5 => 1, + 21 => 1, + 30 => 1, + 46 => 1, + 63 => 1, + 70 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc new file mode 100644 index 000000000..703393396 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NamespaceDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 9 => 1, + 17 => 1, + 19 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc new file mode 100644 index 000000000..61befc9e7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc @@ -0,0 +1,43 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed new file mode 100644 index 000000000..6579613b1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed @@ -0,0 +1,27 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc new file mode 100644 index 000000000..8b290950b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc @@ -0,0 +1,16 @@ + +

    diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc new file mode 100644 index 000000000..1fdaccd38 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc @@ -0,0 +1,47 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc new file mode 100644 index 000000000..dee568699 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc @@ -0,0 +1 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class UseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'UseDeclarationUnitTest.2.inc': + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 16 => 1, + ]; + case 'UseDeclarationUnitTest.3.inc': + return [ + 4 => 1, + 6 => 1, + ]; + case 'UseDeclarationUnitTest.5.inc': + return [ + 5 => 1, + 6 => 1, + 8 => 1, + 14 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 21 => 1, + 28 => 1, + 30 => 1, + 35 => 1, + ]; + case 'UseDeclarationUnitTest.10.inc': + case 'UseDeclarationUnitTest.11.inc': + case 'UseDeclarationUnitTest.12.inc': + case 'UseDeclarationUnitTest.13.inc': + case 'UseDeclarationUnitTest.14.inc': + case 'UseDeclarationUnitTest.16.inc': + case 'UseDeclarationUnitTest.17.inc': + return [2 => 1]; + case 'UseDeclarationUnitTest.15.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml new file mode 100644 index 000000000..ba5bd4e0b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml @@ -0,0 +1,218 @@ + + + The PSR-2 coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml new file mode 100644 index 000000000..fc6ccbd6a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ['bar']; +]]> + + + [ 'bar' ]; +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml new file mode 100644 index 000000000..ce4b9ae68 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml @@ -0,0 +1,117 @@ + + + + + + array keyword must be lowercase. + ]]> + + + + + + + + + + + array keyword. + ]]> + + + + 'value1', + 'key2' => 'value2', + ); + ]]> + + + 'value1', + 'key2' => 'value2', + ); + ]]> + + + + array keyword. The closing parenthesis must be aligned with the start of the array keyword. + ]]> + + + + 'key1' => 'value1', + 'key2' => 'value2', + ); + ]]> + + + 'key1' => 'value1', + 'key2' => 'value2', +); + ]]> + + + + + + + + => 'ValueTen', + 'keyTwenty' => 'ValueTwenty', + ); + ]]> + + + => 'ValueTen', + 'keyTwenty' => 'ValueTwenty', + ); + ]]> + + + + + + + + 'value1', + 'key2' => 'value2', + 'key3' => 'value3', + ); + ]]> + + + 'value1', + 'key2' => 'value2', + 'key3' => 'value3' + ); + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml new file mode 100644 index 000000000..89fcb5de8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + final class Foo extends Bar +{ +} +]]> + + + Final Class Foo Extends Bar +{ +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml new file mode 100644 index 000000000..59d193ffd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml @@ -0,0 +1,63 @@ + + + + + + + self::foo(); +]]> + + + SELF::foo(); +]]> + + + + + ::foo(); +]]> + + + :: foo(); +]]> + + + + + self::bar(); + } +} +]]> + + + Foo +{ + public static function bar() + { + } + + public static function baz() + { + Foo::bar(); + } +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml new file mode 100644 index 000000000..414b89a34 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml @@ -0,0 +1,39 @@ + + + + + + + * @see foo() + */ +]]> + + + * @see foo() +*/ +]]> + + + + + @see foo() + */ +]]> + + + @see foo() + */ +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml new file mode 100644 index 000000000..81df2e3fd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml @@ -0,0 +1,32 @@ + + + + + + + @throws Exception all the time + * @return void + */ +function foo() +{ + throw new Exception('Danger!'); +} +]]> + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml new file mode 100644 index 000000000..87c618137 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $foo as $bar => $baz) { + echo $baz; +} +]]> + + + $foo as $bar=>$baz ) { + echo $baz; +} +]]> + + + + + as $bar => $baz) { + echo $baz; +} +]]> + + + AS $bar => $baz) { + echo $baz; +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml new file mode 100644 index 000000000..bbc439230 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml @@ -0,0 +1,55 @@ + + + + + + + $i = 0; $i < 10; $i++) { + echo $i; +} +]]> + + + $i = 0; $i < 10; $i++ ) { + echo $i; +} +]]> + + + + + ; $i < 10; $i++) { + echo $i; +} +]]> + + + ; $i < 10 ; $i++) { + echo $i; +} +]]> + + + + + $i < 10; $i++) { + echo $i; +} +]]> + + + $i < 10;$i++) { + echo $i; +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml new file mode 100644 index 000000000..699f1f092 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml @@ -0,0 +1,23 @@ + + + + + + + if ($foo) { + $bar = true; +} +]]> + + + IF ($foo) { + $bar = true; +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml new file mode 100644 index 000000000..a890aba68 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml @@ -0,0 +1,23 @@ + + + + + + + isset($foo)) { + echo $foo; +} +]]> + + + isSet($foo)) { + echo $foo; +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml new file mode 100644 index 000000000..46e8a8f32 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml @@ -0,0 +1,25 @@ + + + + + + + function foo() +{ + return true; +} +]]> + + + FUNCTION foo() +{ + return true; +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml new file mode 100644 index 000000000..3c97f54e6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml @@ -0,0 +1,31 @@ + + + + + + + static function bar() + { + return self::$staticMember; + } +} +]]> + + + static function bar() + { + return $this->$staticMember; + } +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml new file mode 100644 index 000000000..030f2a68c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + "Hello"; +]]> + + + ("Hello"); +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml new file mode 100644 index 000000000..0fb195cb6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + int)'42'; +]]> + + + int )'42'; +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml new file mode 100644 index 000000000..d2bc26479 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml @@ -0,0 +1,41 @@ + + + + + + + { +} +]]> + + + { +} +]]> + + + + + return 42; +} +]]> + + + + return 42; +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml new file mode 100644 index 000000000..608bed0b4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + "hi"; +]]> + + + "hi"; +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml new file mode 100644 index 000000000..c6194d71f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml @@ -0,0 +1,19 @@ + + + ) should not have any space around it. + ]]> + + + + ->bar(); +]]> + + + -> bar(); +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml new file mode 100644 index 000000000..8cadf6692 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + static function foo() +{ +} +]]> + + + static function foo() +{ +} +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml new file mode 100644 index 000000000..7b2279529 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ; +]]> + + + ; +]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php new file mode 100644 index 000000000..ee63dead1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php @@ -0,0 +1,95 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ArrayBracketSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET + && isset($tokens[$stackPtr]['bracket_closer']) === false) + || ($tokens[$stackPtr]['code'] === T_CLOSE_SQUARE_BRACKET + && isset($tokens[$stackPtr]['bracket_opener']) === false) + ) { + // Bow out for parse error/during live coding. + return; + } + + // Square brackets can not have a space before them. + $prevType = $tokens[($stackPtr - 1)]['code']; + if ($prevType === T_WHITESPACE) { + $nonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 2), null, true); + $expected = $tokens[$nonSpace]['content'].$tokens[$stackPtr]['content']; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).$tokens[$stackPtr]['content']; + $error = 'Space found before square bracket; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeBracket', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + + // Open square brackets can't ever have spaces after them. + if ($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET) { + $nextType = $tokens[($stackPtr + 1)]['code']; + if ($nextType === T_WHITESPACE) { + $nonSpace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 2), null, true); + $expected = $tokens[$stackPtr]['content'].$tokens[$nonSpace]['content']; + $found = $phpcsFile->getTokensAsString($stackPtr, ($nonSpace - $stackPtr + 1)); + $error = 'Space found after square bracket; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterBracket', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php new file mode 100644 index 000000000..b45a4709d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php @@ -0,0 +1,895 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ArrayDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + // Array keyword should be lower case. + if ($tokens[$stackPtr]['content'] !== strtolower($tokens[$stackPtr]['content'])) { + if ($tokens[$stackPtr]['content'] === strtoupper($tokens[$stackPtr]['content'])) { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'upper'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'mixed'); + } + + $error = 'Array keyword should be lower case; expected "array" but found "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotLowerCase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'array'); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'lower'); + } + + $arrayStart = $tokens[$stackPtr]['parenthesis_opener']; + if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) { + return; + } + + $arrayEnd = $tokens[$arrayStart]['parenthesis_closer']; + + if ($arrayStart !== ($stackPtr + 1)) { + $error = 'There must be no space between the "array" keyword and the opening parenthesis'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $arrayStart, true); + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true) { + // We don't have anywhere to put the comment, so don't attempt to fix it. + $phpcsFile->addError($error, $stackPtr, 'SpaceAfterKeyword'); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $arrayStart; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + $arrayStart = $stackPtr; + $arrayEnd = $tokens[$stackPtr]['bracket_closer']; + }//end if + + // Check for empty arrays. + $content = $phpcsFile->findNext(T_WHITESPACE, ($arrayStart + 1), ($arrayEnd + 1), true); + if ($content === $arrayEnd) { + // Empty array, but if the brackets aren't together, there's a problem. + if (($arrayEnd - $arrayStart) !== 1) { + $error = 'Empty array declaration must have no space between the parentheses'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceInEmptyArray'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // We can return here because there is nothing else to check. All code + // below can assume that the array is not empty. + return; + } + + if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) { + $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd); + } else { + $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd); + } + + }//end process() + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + + // Check if there are multiple values. If so, then it has to be multiple lines + // unless it is contained inside a function call or condition. + $valueCount = 0; + $commas = []; + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + // Skip bracketed statements, like function calls. + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_COMMA) { + // Before counting this comma, make sure we are not + // at the end of the array. + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $arrayEnd, true); + if ($next !== false) { + $valueCount++; + $commas[] = $i; + } else { + // There is a comma at the end of a single line array. + $error = 'Comma not allowed after last value in single-line array declaration'; + $fix = $phpcsFile->addFixableError($error, $i, 'CommaAfterLast'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + }//end for + + // Now check each of the double arrows (if any). + $nextArrow = $arrayStart; + while (($nextArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, ($nextArrow + 1), $arrayEnd)) !== false) { + if ($tokens[($nextArrow - 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($nextArrow - 1)]['content']; + $error = 'Expected 1 space between "%s" and double arrow; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceBeforeDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($nextArrow, ' '); + } + } else { + $spaceLength = $tokens[($nextArrow - 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($nextArrow - 2)]['content']; + $error = 'Expected 1 space between "%s" and double arrow; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceBeforeDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextArrow - 1), ' '); + } + } + }//end if + + if ($tokens[($nextArrow + 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($nextArrow + 1)]['content']; + $error = 'Expected 1 space between double arrow and "%s"; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceAfterDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($nextArrow, ' '); + } + } else { + $spaceLength = $tokens[($nextArrow + 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($nextArrow + 2)]['content']; + $error = 'Expected 1 space between double arrow and "%s"; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceAfterDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextArrow + 1), ' '); + } + } + }//end if + }//end while + + if ($valueCount > 0) { + $nestedParenthesis = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + $nestedParenthesis = array_pop($nested); + } + + if ($nestedParenthesis === false + || $tokens[$nestedParenthesis]['line'] !== $tokens[$stackPtr]['line'] + ) { + $error = 'Array with multiple values cannot be declared on a single line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLineNotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($arrayStart); + + if ($tokens[($arrayEnd - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($arrayEnd); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + // We have a multiple value array that is inside a condition or + // function. Check its spacing is correct. + foreach ($commas as $comma) { + if ($tokens[($comma + 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($comma + 1)]['content']; + $error = 'Expected 1 space between comma and "%s"; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $comma, 'NoSpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($comma, ' '); + } + } else { + $spaceLength = $tokens[($comma + 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($comma + 2)]['content']; + $error = 'Expected 1 space between comma and "%s"; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($comma + 1), ' '); + } + } + }//end if + + if ($tokens[($comma - 1)]['code'] === T_WHITESPACE) { + $content = $tokens[($comma - 2)]['content']; + $spaceLength = $tokens[($comma - 1)]['length']; + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($comma - 1), ''); + } + } + }//end foreach + }//end if + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + $keywordStart = $tokens[$stackPtr]['column']; + + // Check the closing bracket is on a new line. + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), $arrayStart, true); + if ($tokens[$lastContent]['line'] === $tokens[$arrayEnd]['line']) { + $error = 'Closing parenthesis of array declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($arrayEnd); + } + } else if ($tokens[$arrayEnd]['column'] !== $keywordStart) { + // Check the closing bracket is lined up under the "a" in array. + $expected = ($keywordStart - 1); + $found = ($tokens[$arrayEnd]['column'] - 1); + $error = 'Closing parenthesis not aligned correctly; expected %s space(s) but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($arrayEnd - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), str_repeat(' ', $expected)); + } + } + }//end if + + $keyUsed = false; + $singleUsed = false; + $indices = []; + $maxLength = 0; + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $lastToken = $tokens[$stackPtr]['parenthesis_opener']; + } else { + $lastToken = $stackPtr; + } + + // Find all the double arrows that reside in this scope. + for ($nextToken = ($stackPtr + 1); $nextToken < $arrayEnd; $nextToken++) { + // Skip bracketed statements, like function calls. + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS + && (isset($tokens[$nextToken]['parenthesis_owner']) === false + || $tokens[$nextToken]['parenthesis_owner'] !== $stackPtr) + ) { + $nextToken = $tokens[$nextToken]['parenthesis_closer']; + continue; + } + + if ($tokens[$nextToken]['code'] === T_ARRAY + || $tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY + || $tokens[$nextToken]['code'] === T_CLOSURE + || $tokens[$nextToken]['code'] === T_FN + || $tokens[$nextToken]['code'] === T_MATCH + ) { + // Let subsequent calls of this test handle nested arrays. + if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) { + $indices[] = ['value' => $nextToken]; + $lastToken = $nextToken; + } + + if ($tokens[$nextToken]['code'] === T_ARRAY) { + $nextToken = $tokens[$tokens[$nextToken]['parenthesis_opener']]['parenthesis_closer']; + } else if ($tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY) { + $nextToken = $tokens[$nextToken]['bracket_closer']; + } else { + // T_CLOSURE. + $nextToken = $tokens[$nextToken]['scope_closer']; + } + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_COMMA) { + $nextToken--; + } else { + $lastToken = $nextToken; + } + + continue; + }//end if + + if ($tokens[$nextToken]['code'] !== T_DOUBLE_ARROW && $tokens[$nextToken]['code'] !== T_COMMA) { + continue; + } + + $currentEntry = []; + + if ($tokens[$nextToken]['code'] === T_COMMA) { + $stackPtrCount = 0; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']); + } + + $commaCount = 0; + if (isset($tokens[$nextToken]['nested_parenthesis']) === true) { + $commaCount = count($tokens[$nextToken]['nested_parenthesis']); + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + // Remove parenthesis that are used to define the array. + $commaCount--; + } + } + + if ($commaCount > $stackPtrCount) { + // This comma is inside more parenthesis than the ARRAY keyword, + // then there it is actually a comma used to separate arguments + // in a function call. + continue; + } + + if ($keyUsed === true && $tokens[$lastToken]['code'] === T_COMMA) { + $error = 'No key specified for array entry; first entry specifies key'; + $phpcsFile->addError($error, $nextToken, 'NoKeySpecified'); + return; + } + + if ($keyUsed === false) { + if ($tokens[($nextToken - 1)]['code'] === T_WHITESPACE) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextToken - 1), null, true); + if (($tokens[$prev]['code'] !== T_END_HEREDOC + && $tokens[$prev]['code'] !== T_END_NOWDOC) + || $tokens[($nextToken - 1)]['line'] === $tokens[$nextToken]['line'] + ) { + if ($tokens[($nextToken - 1)]['content'] === $phpcsFile->eolChar) { + $spaceLength = 'newline'; + } else { + $spaceLength = $tokens[($nextToken - 1)]['length']; + } + + $error = 'Expected 0 spaces before comma; %s found'; + $data = [$spaceLength]; + + // The error is only fixable if there is only whitespace between the tokens. + if ($prev === $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), null, true)) { + $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextToken - 1), ''); + } + } else { + $phpcsFile->addError($error, $nextToken, 'SpaceBeforeComma', $data); + } + } + }//end if + + $valueContent = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($lastToken + 1), + $nextToken, + true + ); + + $indices[] = ['value' => $valueContent]; + $singleUsed = true; + }//end if + + $lastToken = $nextToken; + continue; + }//end if + + if ($tokens[$nextToken]['code'] === T_DOUBLE_ARROW) { + if ($singleUsed === true) { + $error = 'Key specified for array entry; first entry has no key'; + $phpcsFile->addError($error, $nextToken, 'KeySpecified'); + return; + } + + $currentEntry['arrow'] = $nextToken; + $keyUsed = true; + + // Find the start of index that uses this double arrow. + $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), $arrayStart, true); + $indexStart = $phpcsFile->findStartOfStatement($indexEnd); + + if ($indexStart === $indexEnd) { + $currentEntry['index'] = $indexEnd; + $currentEntry['index_content'] = $tokens[$indexEnd]['content']; + $currentEntry['index_length'] = $tokens[$indexEnd]['length']; + } else { + $currentEntry['index'] = $indexStart; + $currentEntry['index_content'] = ''; + $currentEntry['index_length'] = 0; + for ($i = $indexStart; $i <= $indexEnd; $i++) { + $currentEntry['index_content'] .= $tokens[$i]['content']; + $currentEntry['index_length'] += $tokens[$i]['length']; + } + } + + if ($maxLength < $currentEntry['index_length']) { + $maxLength = $currentEntry['index_length']; + } + + // Find the value of this index. + $nextContent = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($nextToken + 1), + $arrayEnd, + true + ); + + $currentEntry['value'] = $nextContent; + $indices[] = $currentEntry; + $lastToken = $nextToken; + }//end if + }//end for + + // Check for multi-line arrays that should be single-line. + $singleValue = false; + + if (empty($indices) === true) { + $singleValue = true; + } else if (count($indices) === 1 && $tokens[$lastToken]['code'] === T_COMMA) { + // There may be another array value without a comma. + $exclude = Tokens::$emptyTokens; + $exclude[] = T_COMMA; + $nextContent = $phpcsFile->findNext($exclude, ($indices[0]['value'] + 1), $arrayEnd, true); + if ($nextContent === false) { + $singleValue = true; + } + } + + if ($singleValue === true) { + // Before we complain, make sure the single value isn't a here/nowdoc. + $next = $phpcsFile->findNext(Tokens::$heredocTokens, ($arrayStart + 1), ($arrayEnd - 1)); + if ($next === false) { + // Array cannot be empty, so this is a multi-line array with + // a single value. It should be defined on single line. + $error = 'Multi-line array contains a single value; use single-line array instead'; + $errorCode = 'MultiLineNotAllowed'; + + $find = Tokens::$phpcsCommentTokens; + $find[] = T_COMMENT; + $comment = $phpcsFile->findNext($find, ($arrayStart + 1), $arrayEnd); + if ($comment === false) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode); + } else { + $fix = false; + $phpcsFile->addError($error, $stackPtr, $errorCode); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + for ($i = ($arrayEnd - 1); $i > $arrayStart; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + }//end if + + /* + This section checks for arrays that don't specify keys. + + Arrays such as: + array( + 'aaa', + 'bbb', + 'd', + ); + */ + + if ($keyUsed === false && empty($indices) === false) { + $count = count($indices); + $lastIndex = $indices[($count - 1)]['value']; + + $trailingContent = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($arrayEnd - 1), + $lastIndex, + true + ); + + if ($tokens[$trailingContent]['code'] !== T_COMMA) { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no'); + $error = 'Comma required after last value in array declaration'; + $fix = $phpcsFile->addFixableError($error, $trailingContent, 'NoCommaAfterLast'); + if ($fix === true) { + $phpcsFile->fixer->addContent($trailingContent, ','); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes'); + } + + foreach ($indices as $valuePosition => $value) { + if (empty($value['value']) === true) { + // Array was malformed and we couldn't figure out + // the array value correctly, so we have to ignore it. + // Other parts of this sniff will correct the error. + continue; + } + + $valuePointer = $value['value']; + + $ignoreTokens = [ + T_WHITESPACE => T_WHITESPACE, + T_COMMA => T_COMMA, + ]; + $ignoreTokens += Tokens::$castTokens; + + if ($tokens[$valuePointer]['code'] === T_CLOSURE + || $tokens[$valuePointer]['code'] === T_FN + ) { + $ignoreTokens += [T_STATIC => T_STATIC]; + } + + $previous = $phpcsFile->findPrevious($ignoreTokens, ($valuePointer - 1), ($arrayStart + 1), true); + if ($previous === false) { + $previous = $stackPtr; + } + + $previousIsWhitespace = $tokens[($valuePointer - 1)]['code'] === T_WHITESPACE; + if ($tokens[$previous]['line'] === $tokens[$valuePointer]['line']) { + $error = 'Each value in a multi-line array must be on a new line'; + if ($valuePosition === 0) { + $error = 'The first value in a multi-value array must be on a new line'; + } + + $fix = $phpcsFile->addFixableError($error, $valuePointer, 'ValueNoNewline'); + if ($fix === true) { + if ($previousIsWhitespace === true) { + $phpcsFile->fixer->replaceToken(($valuePointer - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($valuePointer); + } + } + } else if ($previousIsWhitespace === true) { + $expected = $keywordStart; + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $valuePointer, true); + $found = ($tokens[$first]['column'] - 1); + if ($found !== $expected) { + $error = 'Array value not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'ValueNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($first - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), str_repeat(' ', $expected)); + } + } + } + }//end if + }//end foreach + }//end if + + /* + Below the actual indentation of the array is checked. + Errors will be thrown when a key is not aligned, when + a double arrow is not aligned, and when a value is not + aligned correctly. + If an error is found in one of the above areas, then errors + are not reported for the rest of the line to avoid reporting + spaces and columns incorrectly. Often fixing the first + problem will fix the other 2 anyway. + + For example: + + $a = array( + 'index' => '2', + ); + + or + + $a = [ + 'index' => '2', + ]; + + In this array, the double arrow is indented too far, but this + will also cause an error in the value's alignment. If the arrow were + to be moved back one space however, then both errors would be fixed. + */ + + $indicesStart = ($keywordStart + 1); + foreach ($indices as $valuePosition => $index) { + $valuePointer = $index['value']; + if ($valuePointer === false) { + // Syntax error or live coding. + continue; + } + + if (isset($index['index']) === false) { + // Array value only. + continue; + } + + $indexPointer = $index['index']; + $indexLine = $tokens[$indexPointer]['line']; + + $previous = $phpcsFile->findPrevious([T_WHITESPACE, T_COMMA], ($indexPointer - 1), ($arrayStart + 1), true); + if ($previous === false) { + $previous = $stackPtr; + } + + if ($tokens[$previous]['line'] === $indexLine) { + $error = 'Each index in a multi-line array must be on a new line'; + if ($valuePosition === 0) { + $error = 'The first index in a multi-value array must be on a new line'; + } + + $fix = $phpcsFile->addFixableError($error, $indexPointer, 'IndexNoNewline'); + if ($fix === true) { + if ($tokens[($indexPointer - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($indexPointer - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($indexPointer); + } + } + + continue; + } + + if ($tokens[$indexPointer]['column'] !== $indicesStart && ($indexPointer - 1) !== $arrayStart) { + $expected = ($indicesStart - 1); + $found = ($tokens[$indexPointer]['column'] - 1); + $error = 'Array key not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $indexPointer, 'KeyNotAligned', $data); + if ($fix === true) { + if ($found === 0 || $tokens[($indexPointer - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent(($indexPointer - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($indexPointer - 1), str_repeat(' ', $expected)); + } + } + } + + $arrowStart = ($tokens[$indexPointer]['column'] + $maxLength + 1); + if ($tokens[$index['arrow']]['column'] !== $arrowStart) { + $expected = ($arrowStart - ($index['index_length'] + $tokens[$indexPointer]['column'])); + $found = ($tokens[$index['arrow']]['column'] - ($index['index_length'] + $tokens[$indexPointer]['column'])); + $error = 'Array double arrow not aligned correctly; expected %s space(s) but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'DoubleArrowNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($index['arrow'] - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($index['arrow'] - 1), str_repeat(' ', $expected)); + } + } + + continue; + } + + $valueStart = ($arrowStart + 3); + if ($tokens[$valuePointer]['column'] !== $valueStart) { + $expected = ($valueStart - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column'])); + $found = ($tokens[$valuePointer]['column'] - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column'])); + if ($found < 0) { + $found = 'newline'; + } + + $error = 'Array value not aligned correctly; expected %s space(s) but found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'ValueNotAligned', $data); + if ($fix === true) { + if ($found === 'newline') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($valuePointer - 1), null, true); + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $valuePointer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken(($valuePointer - 1), str_repeat(' ', $expected)); + $phpcsFile->fixer->endChangeset(); + } else if ($found === 0) { + $phpcsFile->fixer->addContent(($valuePointer - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($valuePointer - 1), str_repeat(' ', $expected)); + } + } + }//end if + + // Check each line ends in a comma. + $valueStart = $valuePointer; + $nextComma = false; + + $end = $phpcsFile->findEndOfStatement($valueStart); + if ($end === false) { + $valueEnd = $valueStart; + } else if ($tokens[$end]['code'] === T_COMMA) { + $valueEnd = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($end - 1), $valueStart, true); + $nextComma = $end; + } else { + $valueEnd = $end; + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $arrayEnd, true); + if ($next !== false && $tokens[$next]['code'] === T_COMMA) { + $nextComma = $next; + } + } + + $valueLine = $tokens[$valueEnd]['line']; + if ($tokens[$valueEnd]['code'] === T_END_HEREDOC || $tokens[$valueEnd]['code'] === T_END_NOWDOC) { + $valueLine++; + } + + if ($nextComma === false || ($tokens[$nextComma]['line'] !== $valueLine)) { + $error = 'Each line in an array declaration must end in a comma'; + $fix = $phpcsFile->addFixableError($error, $valuePointer, 'NoComma'); + + if ($fix === true) { + // Find the end of the line and put a comma there. + for ($i = ($valuePointer + 1); $i <= $arrayEnd; $i++) { + if ($tokens[$i]['line'] > $valueLine) { + break; + } + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore(($i - 1), ','); + if ($nextComma !== false) { + $phpcsFile->fixer->replaceToken($nextComma, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + // Check that there is no space before the comma. + if ($nextComma !== false && $tokens[($nextComma - 1)]['code'] === T_WHITESPACE) { + // Here/nowdoc closing tags must have the comma on the next line. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextComma - 1), null, true); + if ($tokens[$prev]['code'] !== T_END_HEREDOC && $tokens[$prev]['code'] !== T_END_NOWDOC) { + $content = $tokens[($nextComma - 2)]['content']; + $spaceLength = $tokens[($nextComma - 1)]['length']; + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextComma, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextComma - 1), ''); + } + } + } + }//end foreach + + }//end processMultiLineArray() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php new file mode 100644 index 000000000..a9a55fa86 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php @@ -0,0 +1,134 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionClosingBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_CLOSE_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $stackPtr; + while (true) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($next === false) { + return; + } + + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$stackPtr]['line'] + ) { + // Trailing comment. + continue; + } + + break; + } + + if ($tokens[$next]['code'] !== T_CLOSE_TAG) { + $found = (($tokens[$next]['line'] - $tokens[$stackPtr]['line']) - 1); + if ($found !== 1) { + $error = 'Expected one blank line after closing brace of class definition; %s found'; + $data = [max(0, $found)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterClose', $data); + + if ($fix === true) { + $firstOnLine = $next; + while ($tokens[$firstOnLine]['column'] !== 1) { + --$firstOnLine; + } + + if ($found < 0) { + // Next statement on same line as the closing brace. + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($found === 0) { + // Next statement on next line, no blank line. + $phpcsFile->fixer->addContentBefore($firstOnLine, $phpcsFile->eolChar); + } else { + // Too many blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($firstOnLine - 1); $i > $stackPtr; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($firstOnLine, $phpcsFile->eolChar.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + // Ignore nested style definitions from here on. The spacing before the closing brace + // (a single blank line) will be enforced by the above check, which ensures there is a + // blank line after the last nested class. + $found = $phpcsFile->findPrevious( + T_CLOSE_CURLY_BRACKET, + ($stackPtr - 1), + $tokens[$stackPtr]['bracket_opener'] + ); + + if ($found !== false) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev === false) { + return; + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Closing brace of class definition must be on new line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($stackPtr); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php new file mode 100644 index 000000000..4b7efd99a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php @@ -0,0 +1,111 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionNameSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Do not check nested style definitions as, for example, in @media style rules. + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); + if ($nested !== false) { + return; + } + + // Find the first blank line before this opening brace, unless we get + // to another style definition, comment or the start of the file. + $endTokens = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_OPEN_TAG => T_OPEN_TAG, + ]; + $endTokens += Tokens::$commentTokens; + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + $foundContent = false; + $currentLine = $tokens[$prev]['line']; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if (isset($endTokens[$tokens[$i]['code']]) === true) { + break; + } + + if ($tokens[$i]['line'] === $currentLine) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundContent = true; + } + + continue; + } + + // We changed lines. + if ($foundContent === false) { + // Before we throw an error, make sure we are not looking + // at a gap before the style definition. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $i, null, true); + if ($prev !== false + && isset($endTokens[$tokens[$prev]['code']]) === false + ) { + $error = 'Blank lines are not allowed between class names'; + $phpcsFile->addError($error, ($i + 1), 'BlankLinesFound'); + } + + break; + } + + $foundContent = false; + $currentLine = $tokens[$i]['line']; + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php new file mode 100644 index 000000000..e56dad730 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php @@ -0,0 +1,176 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionOpeningBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($prevNonWhitespace !== false) { + $length = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$prevNonWhitespace]['line']) { + $length = 'newline'; + } else if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($stackPtr - 1)]['content'], "\t") !== false) { + $length = 'tab'; + } else { + $length = $tokens[($stackPtr - 1)]['length']; + } + } + + if ($length === 0) { + $error = 'Expected 1 space before opening brace of class definition; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoneBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } else if ($length !== 1) { + $error = 'Expected 1 space before opening brace of class definition; %s found'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr - 1); $i > $prevNonWhitespace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($tokens[$nextNonEmpty]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening brace should be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBefore'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + + // Remove potentially left over trailing whitespace. + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Check for nested class definitions. + $found = $phpcsFile->findNext( + T_OPEN_CURLY_BRACKET, + ($stackPtr + 1), + $tokens[$stackPtr]['bracket_closer'] + ); + + if ($found === false) { + // Not nested. + return; + } + + $lastOnLine = $stackPtr; + for ($lastOnLine; $lastOnLine < $tokens[$stackPtr]['bracket_closer']; $lastOnLine++) { + if ($tokens[$lastOnLine]['line'] !== $tokens[($lastOnLine + 1)]['line']) { + break; + } + } + + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($lastOnLine + 1), null, true); + if ($nextNonWhiteSpace === false) { + return; + } + + $foundLines = ($tokens[$nextNonWhiteSpace]['line'] - $tokens[$stackPtr]['line'] - 1); + if ($foundLines !== 1) { + $error = 'Expected 1 blank line after opening brace of nesting class definition; %s found'; + $data = [max(0, $foundLines)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AfterNesting', $data); + + if ($fix === true) { + $firstOnNextLine = $nextNonWhiteSpace; + while ($tokens[$firstOnNextLine]['column'] !== 1) { + --$firstOnNextLine; + } + + if ($found < 0) { + // First statement on same line as the opening brace. + $phpcsFile->fixer->addContentBefore($nextNonWhiteSpace, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($found === 0) { + // Next statement on next line, no blank line. + $phpcsFile->fixer->addNewlineBefore($firstOnNextLine); + } else { + // Too many blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($firstOnNextLine - 1); $i > $stackPtr; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($firstOnNextLine, $phpcsFile->eolChar.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php new file mode 100644 index 000000000..8548a7218 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ColonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_COLON]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_STYLE) { + // The colon is not part of a style definition. + return; + } + + if ($tokens[$prev]['content'] === 'progid') { + // Special case for IE filters. + return; + } + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $error = 'There must be no space before a colon in a style definition'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['code'] === T_STYLE) { + // Empty style definition, ignore it. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after colon in style definition; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoneAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else { + $content = $tokens[($stackPtr + 1)]['content']; + if (strpos($content, $phpcsFile->eolChar) === false) { + $length = strlen($content); + if ($length !== 1) { + $error = 'Expected 1 space after colon in style definition; %s found'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } else { + $error = 'Expected 1 space after colon in style definition; newline found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AfterNewline'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php new file mode 100644 index 000000000..6b071ea7c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ColourDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_COLOUR]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $colour = $tokens[$stackPtr]['content']; + + $expected = strtoupper($colour); + if ($colour !== $expected) { + $error = 'CSS colours must be defined in uppercase; expected %s but found %s'; + $data = [ + $expected, + $colour, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotUpper', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + // Now check if shorthand can be used. + if (strlen($colour) !== 7) { + return; + } + + if ($colour[1] === $colour[2] && $colour[3] === $colour[4] && $colour[5] === $colour[6]) { + $expected = '#'.$colour[1].$colour[3].$colour[5]; + $error = 'CSS colours must use shorthand if available; expected %s but found %s'; + $data = [ + $expected, + $colour, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Shorthand', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php new file mode 100644 index 000000000..def95c1ef --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowMultipleStyleDefinitionsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(T_STYLE, ($stackPtr + 1)); + if ($next === false) { + return; + } + + if ($tokens[$next]['content'] === 'progid') { + // Special case for IE filters. + return; + } + + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Each style definition must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $next, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($next); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php new file mode 100644 index 000000000..d489cb1ba --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DuplicateClassDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the content of each class definition name. + $classNames = []; + $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1)); + if ($next === false) { + // No class definitions in the file. + return; + } + + // Save the class names in a "scope", + // to prevent false positives with @media blocks. + $scope = 'main'; + + $find = [ + T_CLOSE_CURLY_BRACKET, + T_OPEN_CURLY_BRACKET, + T_OPEN_TAG, + ]; + + while ($next !== false) { + $prev = $phpcsFile->findPrevious($find, ($next - 1)); + + // Check if an inner block was closed. + $beforePrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($beforePrev !== false + && $tokens[$beforePrev]['code'] === T_CLOSE_CURLY_BRACKET + ) { + $scope = 'main'; + } + + // Create a sorted name for the class so we can compare classes + // even when the individual names are all over the place. + $name = ''; + for ($i = ($prev + 1); $i < $next; $i++) { + $name .= $tokens[$i]['content']; + } + + $name = trim($name); + $name = str_replace("\n", ' ', $name); + $name = preg_replace('|[\s]+|', ' ', $name); + $name = preg_replace('|\s*/\*.*\*/\s*|', '', $name); + $name = str_replace(', ', ',', $name); + + $names = explode(',', $name); + sort($names); + $name = implode(',', $names); + + if ($name[0] === '@') { + // Media block has its own "scope". + $scope = $name; + } else if (isset($classNames[$scope][$name]) === true) { + $first = $classNames[$scope][$name]; + $error = 'Duplicate class definition found; first defined on line %s'; + $data = [$tokens[$first]['line']]; + $phpcsFile->addError($error, $next, 'Found', $data); + } else { + $classNames[$scope][$name] = $next; + } + + $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($next + 1)); + }//end while + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php new file mode 100644 index 000000000..c74797597 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicateStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Find the content of each style definition name. + $styleNames = []; + + $next = $stackPtr; + $end = $tokens[$stackPtr]['bracket_closer']; + + do { + $next = $phpcsFile->findNext([T_STYLE, T_OPEN_CURLY_BRACKET], ($next + 1), $end); + if ($next === false) { + // Class definition is empty. + break; + } + + if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) { + $next = $tokens[$next]['bracket_closer']; + continue; + } + + $name = $tokens[$next]['content']; + if (isset($styleNames[$name]) === true) { + $first = $styleNames[$name]; + $error = 'Duplicate style definition found; first defined on line %s'; + $data = [$tokens[$first]['line']]; + $phpcsFile->addError($error, $next, 'Found', $data); + } else { + $styleNames[$name] = $next; + } + } while ($next !== false); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php new file mode 100644 index 000000000..d3bb9696c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyClassDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($next === false || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + $error = 'Class definition is empty'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php new file mode 100644 index 000000000..05f2e5159 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_COLON; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Style definition is empty'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php new file mode 100644 index 000000000..d8585dc86 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php @@ -0,0 +1,177 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ForbiddenStylesSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of forbidden styles with their alternatives. + * + * The value is NULL if no alternative exists. i.e., the + * style should just not be used. + * + * @var array + */ + protected $forbiddenStyles = [ + '-moz-border-radius' => 'border-radius', + '-webkit-border-radius' => 'border-radius', + '-moz-border-radius-topleft' => 'border-top-left-radius', + '-moz-border-radius-topright' => 'border-top-right-radius', + '-moz-border-radius-bottomright' => 'border-bottom-right-radius', + '-moz-border-radius-bottomleft' => 'border-bottom-left-radius', + '-moz-box-shadow' => 'box-shadow', + '-webkit-box-shadow' => 'box-shadow', + ]; + + /** + * A cache of forbidden style names, for faster lookups. + * + * @var string[] + */ + protected $forbiddenStyleNames = []; + + /** + * If true, forbidden styles will be considered regular expressions. + * + * @var boolean + */ + protected $patternMatch = false; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $this->forbiddenStyleNames = array_keys($this->forbiddenStyles); + + if ($this->patternMatch === true) { + foreach ($this->forbiddenStyleNames as $i => $name) { + $this->forbiddenStyleNames[$i] = '/'.$name.'/i'; + } + } + + return [T_STYLE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $style = strtolower($tokens[$stackPtr]['content']); + $pattern = null; + + if ($this->patternMatch === true) { + $count = 0; + $pattern = preg_replace( + $this->forbiddenStyleNames, + $this->forbiddenStyleNames, + $style, + 1, + $count + ); + + if ($count === 0) { + return; + } + + // Remove the pattern delimiters and modifier. + $pattern = substr($pattern, 1, -2); + } else { + if (in_array($style, $this->forbiddenStyleNames, true) === false) { + return; + } + }//end if + + $this->addError($phpcsFile, $stackPtr, $style, $pattern); + + }//end process() + + + /** + * Generates the error or warning for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden style + * in the token array. + * @param string $style The name of the forbidden style. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError($phpcsFile, $stackPtr, $style, $pattern=null) + { + $data = [$style]; + $error = 'The use of style %s is '; + if ($this->error === true) { + $type = 'Found'; + $error .= 'forbidden'; + } else { + $type = 'Discouraged'; + $error .= 'discouraged'; + } + + if ($pattern === null) { + $pattern = $style; + } + + if ($this->forbiddenStyles[$pattern] !== null) { + $data[] = $this->forbiddenStyles[$pattern]; + if ($this->error === true) { + $fix = $phpcsFile->addFixableError($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); + } else { + $fix = $phpcsFile->addFixableWarning($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); + } + + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $this->forbiddenStyles[$pattern]); + } + } else { + if ($this->error === true) { + $phpcsFile->addError($error, $stackPtr, $type, $data); + } else { + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + } + + }//end addError() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php new file mode 100644 index 000000000..5e35f4e9f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php @@ -0,0 +1,150 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IndentationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $numTokens = (count($tokens) - 2); + $indentLevel = 0; + $nestingLevel = 0; + for ($i = 1; $i < $numTokens; $i++) { + if ($tokens[$i]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true + ) { + // Don't check the indent of comments. + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + $indentLevel++; + + if (isset($tokens[$i]['bracket_closer']) === false) { + // Syntax error or live coding. + // Anything after this would receive incorrect fixes, so bow out. + return; + } + + // Check for nested class definitions. + $found = $phpcsFile->findNext( + T_OPEN_CURLY_BRACKET, + ($i + 1), + $tokens[$i]['bracket_closer'] + ); + + if ($found !== false) { + $nestingLevel = $indentLevel; + } + } + + if (($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$i]['line'] !== $tokens[($i - 1)]['line']) + || ($tokens[($i + 1)]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$i]['line'] === $tokens[($i + 1)]['line']) + ) { + $indentLevel--; + if ($indentLevel === 0) { + $nestingLevel = 0; + } + } + + if ($tokens[$i]['column'] !== 1 + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + ) { + continue; + } + + // We started a new line, so check indent. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $content = str_replace($phpcsFile->eolChar, '', $tokens[$i]['content']); + $foundIndent = strlen($content); + } else { + $foundIndent = 0; + } + + $expectedIndent = ($indentLevel * $this->indent); + if ($expectedIndent > 0 + && strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false + ) { + if ($nestingLevel !== $indentLevel) { + $error = 'Blank lines are not allowed in class definitions'; + $fix = $phpcsFile->addFixableError($error, $i, 'BlankLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else if ($foundIndent !== $expectedIndent) { + $error = 'Line indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Incorrect', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $indent); + } else { + $phpcsFile->fixer->replaceToken($i, $indent); + } + } + }//end if + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php new file mode 100644 index 000000000..c80a639c8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php @@ -0,0 +1,97 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercaseStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + $end = ($tokens[$stackPtr]['bracket_closer'] - 1); + $inStyle = null; + + for ($i = $start; $i <= $end; $i++) { + // Skip nested definitions as they are checked individually. + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_STYLE) { + $inStyle = $tokens[$i]['content']; + } + + if ($tokens[$i]['code'] === T_SEMICOLON) { + $inStyle = null; + } + + if ($inStyle === 'progid') { + // Special case for IE filters. + continue; + } + + if ($tokens[$i]['code'] === T_STYLE + || ($inStyle !== null + && $tokens[$i]['code'] === T_STRING) + ) { + $expected = strtolower($tokens[$i]['content']); + if ($expected !== $tokens[$i]['content']) { + $error = 'Style definitions must be lowercase; expected %s but found %s'; + $data = [ + $expected, + $tokens[$i]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'FoundUpper', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, $expected); + } + } + } + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php new file mode 100644 index 000000000..dbf7d6c95 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class MissingColonSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + $lastLine = $tokens[$stackPtr]['line']; + $end = $tokens[$stackPtr]['bracket_closer']; + + // Do not check nested style definitions as, for example, in @media style rules. + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $end); + if ($nested !== false) { + return; + } + + $foundColon = false; + $foundString = false; + for ($i = ($stackPtr + 1); $i <= $end; $i++) { + if ($tokens[$i]['line'] !== $lastLine) { + // We changed lines. + if ($foundColon === false && $foundString !== false) { + // We didn't find a colon on the previous line. + $error = 'No style definition found on line; check for missing colon'; + $phpcsFile->addError($error, $foundString, 'Found'); + } + + $foundColon = false; + $foundString = false; + $lastLine = $tokens[$i]['line']; + } + + if ($tokens[$i]['code'] === T_STRING) { + $foundString = $i; + } else if ($tokens[$i]['code'] === T_COLON) { + $foundColon = $i; + } + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php new file mode 100644 index 000000000..0a51f501b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php @@ -0,0 +1,93 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NamedColoursSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of named colours. + * + * This is the list of standard colours defined in the CSS specification. + * + * @var array + */ + protected $colourNames = [ + 'aqua' => 'aqua', + 'black' => 'black', + 'blue' => 'blue', + 'fuchsia' => 'fuchsia', + 'gray' => 'gray', + 'green' => 'green', + 'lime' => 'lime', + 'maroon' => 'maroon', + 'navy' => 'navy', + 'olive' => 'olive', + 'orange' => 'orange', + 'purple' => 'purple', + 'red' => 'red', + 'silver' => 'silver', + 'teal' => 'teal', + 'white' => 'white', + 'yellow' => 'yellow', + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr - 1)]['code'] === T_HASH + || $tokens[($stackPtr - 1)]['code'] === T_STRING_CONCAT + ) { + // Class name. + return; + } + + if (isset($this->colourNames[strtolower($tokens[$stackPtr]['content'])]) === true) { + $error = 'Named colours are forbidden; use hex, rgb, or rgba values instead'; + $phpcsFile->addError($error, $stackPtr, 'Forbidden'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php new file mode 100644 index 000000000..1dfbcf676 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php @@ -0,0 +1,101 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpacitySniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'] !== 'opacity') { + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_COLON; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + + if ($next === false + || ($tokens[$next]['code'] !== T_DNUMBER + && $tokens[$next]['code'] !== T_LNUMBER) + ) { + return; + } + + $value = $tokens[$next]['content']; + if ($tokens[$next]['code'] === T_LNUMBER) { + if ($value !== '0' && $value !== '1') { + $error = 'Opacity values must be between 0 and 1'; + $phpcsFile->addError($error, $next, 'Invalid'); + } + } else { + if (strlen($value) > 3) { + $error = 'Opacity values must have a single value after the decimal point'; + $phpcsFile->addError($error, $next, 'DecimalPrecision'); + } else if ($value === '0.0' || $value === '1.0') { + $error = 'Opacity value does not require decimal point; use %s instead'; + $data = [$value[0]]; + $fix = $phpcsFile->addFixableError($error, $next, 'PointNotRequired', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, $value[0]); + } + } else if ($value[0] === '.') { + $error = 'Opacity values must not start with a decimal point; use 0%s instead'; + $data = [$value]; + $fix = $phpcsFile->addFixableError($error, $next, 'StartWithPoint', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, '0'.$value); + } + } else if ($value[0] !== '0') { + $error = 'Opacity values must be between 0 and 1'; + $phpcsFile->addError($error, $next, 'Invalid'); + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php new file mode 100644 index 000000000..fdc168e24 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SemicolonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextStatement = $phpcsFile->findNext([T_STYLE, T_CLOSE_CURLY_BRACKET], ($stackPtr + 1)); + if ($nextStatement === false) { + return; + } + + $ignore = Tokens::$emptyTokens; + if ($tokens[$nextStatement]['code'] === T_STYLE) { + // Allow for star-prefix hack. + $ignore[] = T_MULTIPLY; + } + + $endOfThisStatement = $phpcsFile->findPrevious($ignore, ($nextStatement - 1), null, true); + if ($tokens[$endOfThisStatement]['code'] !== T_SEMICOLON) { + $error = 'Style definitions must end with a semicolon'; + $phpcsFile->addError($error, $endOfThisStatement, 'NotAtEnd'); + return; + } + + if ($tokens[($endOfThisStatement - 1)]['code'] !== T_WHITESPACE) { + return; + } + + // There is a semi-colon, so now find the last token in the statement. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($endOfThisStatement - 1), null, true); + $found = $tokens[($endOfThisStatement - 1)]['length']; + if ($tokens[$prevNonEmpty]['line'] !== $tokens[$endOfThisStatement]['line']) { + $found = 'newline'; + } + + $error = 'Expected 0 spaces before semicolon in style definition; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $prevNonEmpty, 'SpaceFound', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prevNonEmpty, ';'); + $phpcsFile->fixer->replaceToken($endOfThisStatement, ''); + + for ($i = ($endOfThisStatement - 1); $i > $prevNonEmpty; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php new file mode 100644 index 000000000..8f2d9aa8c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php @@ -0,0 +1,181 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ShorthandSizeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of styles that we shouldn't check. + * + * These have values that looks like sizes, but are not. + * + * @var array + */ + protected $excludeStyles = [ + 'background-position' => 'background-position', + 'box-shadow' => 'box-shadow', + 'transform-origin' => 'transform-origin', + '-webkit-transform-origin' => '-webkit-transform-origin', + '-ms-transform-origin' => '-ms-transform-origin', + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Some styles look like shorthand but are not actually a set of 4 sizes. + $style = strtolower($tokens[$stackPtr]['content']); + if (isset($this->excludeStyles[$style]) === true) { + return; + } + + $end = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1)); + if ($end === false) { + // Live coding or parse error. + return; + } + + // Get the whole style content. + $origContent = $phpcsFile->getTokensAsString(($stackPtr + 1), ($end - $stackPtr - 1)); + $origContent = trim($origContent, ':'); + $origContent = trim($origContent); + + // Account for a !important annotation. + $content = $origContent; + if (substr($content, -10) === '!important') { + $content = substr($content, 0, -10); + $content = trim($content); + } + + // Check if this style value is a set of numbers with optional prefixes. + $content = preg_replace('/\s+/', ' ', $content); + $values = []; + $num = preg_match_all( + '/(?:[0-9]+)(?:[a-zA-Z]{2}\s+|%\s+|\s+)/', + $content.' ', + $values, + PREG_SET_ORDER + ); + + // Only interested in styles that have multiple sizes defined. + if ($num < 2) { + return; + } + + // Rebuild the content we matched to ensure we got everything. + $matched = ''; + foreach ($values as $value) { + $matched .= $value[0]; + } + + if ($content !== trim($matched)) { + return; + } + + if ($num === 3) { + $expected = trim($content.' '.$values[1][0]); + $error = 'Shorthand syntax not allowed here; use %s instead'; + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if (substr($origContent, -10) === '!important') { + $expected .= ' !important'; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 2), null, true); + $phpcsFile->fixer->replaceToken($next, $expected); + for ($next++; $next < $end; $next++) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + + if ($num === 2) { + if ($values[0][0] !== $values[1][0]) { + // Both values are different, so it is already shorthand. + return; + } + } else if ($values[0][0] !== $values[2][0] || $values[1][0] !== $values[3][0]) { + // Can't shorthand this. + return; + } + + if ($values[0][0] === $values[1][0]) { + // All values are the same. + $expected = trim($values[0][0]); + } else { + $expected = trim($values[0][0]).' '.trim($values[1][0]); + } + + $error = 'Size definitions must use shorthand if available; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotUsed', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if (substr($origContent, -10) === '!important') { + $expected .= ' !important'; + } + + $next = $phpcsFile->findNext(T_COLON, ($stackPtr + 1)); + $phpcsFile->fixer->addContent($next, ' '.$expected); + for ($next++; $next < $end; $next++) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..3d2c4db1a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,206 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff as PSR2ClassDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDeclarationSniff extends PSR2ClassDeclarationSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // We want all the errors from the PSR2 standard, plus some of our own. + parent::process($phpcsFile, $stackPtr); + + // Check that this is the only class or interface in the file. + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE], ($stackPtr + 1)); + if ($nextClass !== false) { + // We have another, so an error is thrown. + $error = 'Only one interface or class is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleClasses'); + } + + }//end process() + + + /** + * Processes the opening section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processOpen(File $phpcsFile, $stackPtr) + { + parent::processOpen($phpcsFile, $stackPtr); + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($stackPtr - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + + if ($tokens[($stackPtr - 2)]['code'] !== T_ABSTRACT + && $tokens[($stackPtr - 2)]['code'] !== T_FINAL + ) { + if ($spaces !== 0) { + $type = strtolower($tokens[$stackPtr]['content']); + $error = 'Expected 0 spaces before %s keyword; %s found'; + $data = [ + $type, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + } + }//end if + }//end if + + }//end processOpen() + + + /** + * Processes the closing section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + + // Check that the closing brace has one blank line after it. + for ($nextContent = ($closeBrace + 1); $nextContent < $phpcsFile->numTokens; $nextContent++) { + // Ignore comments on the same line as the brace. + if ($tokens[$nextContent]['line'] === $tokens[$closeBrace]['line'] + && ($tokens[$nextContent]['code'] === T_WHITESPACE + || $tokens[$nextContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$nextContent]['code']]) === true) + ) { + continue; + } + + if ($tokens[$nextContent]['code'] !== T_WHITESPACE) { + break; + } + } + + if ($nextContent === $phpcsFile->numTokens) { + // Ignore the line check as this is the very end of the file. + $difference = 1; + } else { + $difference = ($tokens[$nextContent]['line'] - $tokens[$closeBrace]['line'] - 1); + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), $stackPtr, true); + + if ($difference === -1 + || $tokens[$lastContent]['line'] === $tokens[$closeBrace]['line'] + ) { + $error = 'Closing %s brace must be on a line by itself'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'CloseBraceSameLine', $data); + if ($fix === true) { + if ($difference === -1) { + $phpcsFile->fixer->addNewlineBefore($nextContent); + } + + if ($tokens[$lastContent]['line'] === $tokens[$closeBrace]['line']) { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } + } else if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($closeBrace - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + if ($spaces !== 0) { + if ($tokens[($closeBrace - 1)]['line'] !== $tokens[$closeBrace]['line']) { + $error = 'Expected 0 spaces before closing brace; newline found'; + $phpcsFile->addError($error, $closeBrace, 'NewLineBeforeCloseBrace'); + } else { + $error = 'Expected 0 spaces before closing brace; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closeBrace - 1), ''); + } + } + } + } + }//end if + + if ($difference !== -1 && $difference !== 1) { + if ($tokens[$nextContent]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$nextContent]['comment_closer'] + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_FUNCTION) { + return; + } + } + + $error = 'Closing brace of a %s must be followed by a single blank line; found %s'; + $data = [ + $tokens[$stackPtr]['content'], + $difference, + ]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'NewlinesAfterCloseBrace', $data); + if ($fix === true) { + if ($difference === 0) { + $first = $phpcsFile->findFirstOnLine([], $nextContent, true); + $phpcsFile->fixer->addNewlineBefore($first); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closeBrace + 1); $i < $nextContent; $i++) { + if ($tokens[$i]['line'] <= ($tokens[$closeBrace]['line'] + 1)) { + continue; + } else if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processClose() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php new file mode 100644 index 000000000..88a7e0daa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassFileNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $fullPath = basename($phpcsFile->getFilename()); + $fileName = substr($fullPath, 0, strrpos($fullPath, '.')); + if ($fileName === '') { + // No filename probably means STDIN, so we can't do this check. + return; + } + + $tokens = $phpcsFile->getTokens(); + $decName = $phpcsFile->findNext(T_STRING, $stackPtr); + + if ($tokens[$decName]['content'] !== $fileName) { + $error = '%s name doesn\'t match filename; expected "%s %s"'; + $data = [ + ucfirst($tokens[$stackPtr]['content']), + $tokens[$stackPtr]['content'], + $fileName, + ]; + $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php new file mode 100644 index 000000000..a632f81e9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicatePropertySniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OBJECT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $properties = []; + $wantedTokens = [ + T_PROPERTY, + T_OBJECT, + ]; + + $next = $phpcsFile->findNext($wantedTokens, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); + while ($next !== false && $next < $tokens[$stackPtr]['bracket_closer']) { + if ($tokens[$next]['code'] === T_OBJECT) { + // Skip nested objects. + $next = $tokens[$next]['bracket_closer']; + } else { + $propName = $tokens[$next]['content']; + if (isset($properties[$propName]) === true) { + $error = 'Duplicate property definition found for "%s"; previously defined on line %s'; + $data = [ + $propName, + $tokens[$properties[$propName]]['line'], + ]; + $phpcsFile->addError($error, $next, 'Found', $data); + } + + $properties[$propName] = $next; + }//end if + + $next = $phpcsFile->findNext($wantedTokens, ($next + 1), $tokens[$stackPtr]['bracket_closer']); + }//end while + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php new file mode 100644 index 000000000..5f4f78c0a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercaseClassKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $targets = Tokens::$ooScopeTokens; + $targets[] = T_EXTENDS; + $targets[] = T_IMPLEMENTS; + $targets[] = T_ABSTRACT; + $targets[] = T_FINAL; + $targets[] = T_VAR; + $targets[] = T_CONST; + + return $targets; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php new file mode 100644 index 000000000..d17ca44ce --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php @@ -0,0 +1,240 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class SelfMemberReferenceSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Classes_SelfMemberReferenceSniff. + */ + public function __construct() + { + parent::__construct([T_CLASS], [T_DOUBLE_COLON]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a double colon which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_reverse($conditions, true); + foreach ($conditions as $conditionToken => $tokenCode) { + if ($tokenCode === T_CLASS || $tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + break; + } + } + + if ($conditionToken !== $currScope) { + return; + } + + $calledClassName = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($calledClassName === false) { + // Parse error. + return; + } + + if ($tokens[$calledClassName]['code'] === T_SELF) { + if ($tokens[$calledClassName]['content'] !== 'self') { + $error = 'Must use "self::" for local static member reference; found "%s::"'; + $data = [$tokens[$calledClassName]['content']]; + $fix = $phpcsFile->addFixableError($error, $calledClassName, 'IncorrectCase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($calledClassName, 'self'); + } + + return; + } + } else if ($tokens[$calledClassName]['code'] === T_STRING) { + // If the class is called with a namespace prefix, build fully qualified + // namespace calls for both current scope class and requested class. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($calledClassName - 1), null, true); + if ($prevNonEmpty !== false && $tokens[$prevNonEmpty]['code'] === T_NS_SEPARATOR) { + $declarationName = $this->getDeclarationNameWithNamespace($tokens, $calledClassName); + $declarationName = ltrim($declarationName, '\\'); + $fullQualifiedClassName = $this->getNamespaceOfScope($phpcsFile, $currScope); + if ($fullQualifiedClassName === '\\') { + $fullQualifiedClassName = ''; + } else { + $fullQualifiedClassName .= '\\'; + } + + $fullQualifiedClassName .= $phpcsFile->getDeclarationName($currScope); + } else { + $declarationName = $phpcsFile->getDeclarationName($currScope); + $fullQualifiedClassName = $tokens[$calledClassName]['content']; + } + + if ($declarationName === $fullQualifiedClassName) { + // Class name is the same as the current class, which is not allowed. + $error = 'Must use "self::" for local static member reference'; + $fix = $phpcsFile->addFixableError($error, $calledClassName, 'NotUsed'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $currentPointer = ($stackPtr - 1); + while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR + || $tokens[$currentPointer]['code'] === T_STRING + || isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true + ) { + if (isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true) { + --$currentPointer; + continue; + } + + $phpcsFile->fixer->replaceToken($currentPointer, ''); + --$currentPointer; + } + + $phpcsFile->fixer->replaceToken($stackPtr, 'self::'); + $phpcsFile->fixer->endChangeset(); + + // Fix potential whitespace issues in the next loop. + return; + }//end if + }//end if + }//end if + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr - 1)]['length']; + $error = 'Expected 0 spaces before double colon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, ($stackPtr - 1), 'SpaceBefore', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr - 1); $tokens[$i]['code'] === T_WHITESPACE; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + $error = 'Expected 0 spaces after double colon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, ($stackPtr - 1), 'SpaceAfter', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr + 1); $tokens[$i]['code'] === T_WHITESPACE; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + + /** + * Returns the declaration names for classes/interfaces/functions with a namespace. + * + * @param array $tokens Token stack for this file + * @param int $stackPtr The position where the namespace building will start. + * + * @return string + */ + protected function getDeclarationNameWithNamespace(array $tokens, $stackPtr) + { + $nameParts = []; + $currentPointer = $stackPtr; + while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR + || $tokens[$currentPointer]['code'] === T_STRING + || isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true + ) { + if (isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true) { + --$currentPointer; + continue; + } + + $nameParts[] = $tokens[$currentPointer]['content']; + --$currentPointer; + } + + $nameParts = array_reverse($nameParts); + return implode('', $nameParts); + + }//end getDeclarationNameWithNamespace() + + + /** + * Returns the namespace declaration of a file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the search for the + * namespace declaration will start. + * + * @return string + */ + protected function getNamespaceOfScope(File $phpcsFile, $stackPtr) + { + $namespace = '\\'; + $namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr); + + if ($namespaceDeclaration !== false) { + $endOfNamespaceDeclaration = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET], $namespaceDeclaration); + $namespace = $this->getDeclarationNameWithNamespace( + $phpcsFile->getTokens(), + ($endOfNamespaceDeclaration - 1) + ); + } + + return $namespace; + + }//end getNamespaceOfScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php new file mode 100644 index 000000000..ffddd2cde --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ValidClassNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); + return; + } + + // Determine the name of the class or interface. Note that we cannot + // simply look for the first T_STRING because a class name + // starting with the number will be multiple tokens. + $opener = $tokens[$stackPtr]['scope_opener']; + $nameStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $opener, true); + $nameEnd = $phpcsFile->findNext([T_WHITESPACE, T_COLON], $nameStart, $opener); + if ($nameEnd === false) { + $name = $tokens[$nameStart]['content']; + } else { + $name = trim($phpcsFile->getTokensAsString($nameStart, ($nameEnd - $nameStart))); + } + + // Check for PascalCase format. + $valid = Common::isCamelCaps($name, true, true, false); + if ($valid === false) { + $type = ucfirst($tokens[$stackPtr]['content']); + $error = '%s name "%s" is not in PascalCase format'; + $data = [ + $type, + $name, + ]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + $phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'yes'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php new file mode 100644 index 000000000..eb647f5fe --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php @@ -0,0 +1,401 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class BlockCommentSniff implements Sniff +{ + + /** + * The --tab-width CLI value that is being used. + * + * @var integer + */ + private $tabWidth = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->tabWidth === null) { + if (isset($phpcsFile->config->tabWidth) === false || $phpcsFile->config->tabWidth === 0) { + // We have no idea how wide tabs are, so assume 4 spaces for fixing. + $this->tabWidth = 4; + } else { + $this->tabWidth = $phpcsFile->config->tabWidth; + } + } + + $tokens = $phpcsFile->getTokens(); + + // If it's an inline comment, return. + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '/*') { + return; + } + + // If this is a function/class/interface doc block comment, skip it. + // We are only interested in inline doc block comments. + if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_FUNCTION => true, + T_PUBLIC => true, + T_PRIVATE => true, + T_FINAL => true, + T_PROTECTED => true, + T_STATIC => true, + T_ABSTRACT => true, + T_CONST => true, + T_VAR => true, + T_READONLY => true, + ]; + if (isset($ignore[$tokens[$nextToken]['code']]) === true) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] === T_OPEN_TAG) { + return; + } + + $error = 'Block comments must be started with /*'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStart'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, '/*'); + } + + $end = $tokens[$stackPtr]['comment_closer']; + if ($tokens[$end]['content'] !== '*/') { + $error = 'Block comments must be ended with */'; + $fix = $phpcsFile->addFixableError($error, $end, 'WrongEnd'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($end, '*/'); + } + } + + return; + }//end if + + $commentLines = [$stackPtr]; + $nextComment = $stackPtr; + $lastLine = $tokens[$stackPtr]['line']; + $commentString = $tokens[$stackPtr]['content']; + + // Construct the comment into an array. + while (($nextComment = $phpcsFile->findNext(T_WHITESPACE, ($nextComment + 1), null, true)) !== false) { + if ($tokens[$nextComment]['code'] !== $tokens[$stackPtr]['code'] + && isset(Tokens::$phpcsCommentTokens[$tokens[$nextComment]['code']]) === false + ) { + // Found the next bit of code. + break; + } + + if (($tokens[$nextComment]['line'] - 1) !== $lastLine) { + // Not part of the block. + break; + } + + $lastLine = $tokens[$nextComment]['line']; + $commentLines[] = $nextComment; + $commentString .= $tokens[$nextComment]['content']; + if ($tokens[$nextComment]['code'] === T_DOC_COMMENT_CLOSE_TAG + || substr($tokens[$nextComment]['content'], -2) === '*/' + ) { + break; + } + }//end while + + $commentText = str_replace($phpcsFile->eolChar, '', $commentString); + $commentText = trim($commentText, "/* \t"); + if ($commentText === '') { + $error = 'Empty block comment not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $lastToken = array_pop($commentLines); + for ($i = ($stackPtr + 1); $i <= $lastToken; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + if (count($commentLines) === 1) { + $error = 'Single line block comment not allowed; use inline ("// text") comment instead'; + + // Only fix comments when they are the last token on a line. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLine'); + if ($fix === true) { + $comment = '// '.$commentText.$phpcsFile->eolChar; + $phpcsFile->fixer->replaceToken($stackPtr, $comment); + } + } else { + $phpcsFile->addError($error, $stackPtr, 'SingleLine'); + } + + return; + } + + $content = trim($tokens[$stackPtr]['content']); + if ($content !== '/*' && $content !== '/**') { + $error = 'Block comment text must start on a new line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoNewLine'); + if ($fix === true) { + $indent = ''; + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + if (isset($tokens[($stackPtr - 1)]['orig_content']) === true) { + $indent = $tokens[($stackPtr - 1)]['orig_content']; + } else { + $indent = $tokens[($stackPtr - 1)]['content']; + } + } + + $comment = preg_replace( + '/^(\s*\/\*\*?)/', + '$1'.$phpcsFile->eolChar.$indent, + $tokens[$stackPtr]['content'], + 1 + ); + $phpcsFile->fixer->replaceToken($stackPtr, $comment); + } + + return; + }//end if + + $starColumn = $tokens[$stackPtr]['column']; + $hasStars = false; + + // Make sure first line isn't blank. + if (trim($tokens[$commentLines[1]]['content']) === '') { + $error = 'Empty line not allowed at start of comment'; + $fix = $phpcsFile->addFixableError($error, $commentLines[1], 'HasEmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($commentLines[1], ''); + } + } else { + // Check indentation of first line. + $content = $tokens[$commentLines[1]]['content']; + $commentText = ltrim($content); + $leadingSpace = (strlen($content) - strlen($commentText)); + + $expected = ($starColumn + 3); + if ($commentText[0] === '*') { + $expected = $starColumn; + $hasStars = true; + } + + if ($leadingSpace !== $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'First line of comment not aligned correctly; expected %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $commentLines[1], 'FirstLineIndent', $data); + if ($fix === true) { + if (isset($tokens[$commentLines[1]]['orig_content']) === true + && $tokens[$commentLines[1]]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($commentLines[1], $padding.$commentText); + } + }//end if + + if (preg_match('/^\p{Ll}/u', $commentText) === 1) { + $error = 'Block comments must start with a capital letter'; + $phpcsFile->addError($error, $commentLines[1], 'NoCapital'); + } + }//end if + + // Check that each line of the comment is indented past the star. + foreach ($commentLines as $line) { + // First and last lines (comment opener and closer) are handled separately. + if ($line === $commentLines[(count($commentLines) - 1)] || $line === $commentLines[0]) { + continue; + } + + // First comment line was handled above. + if ($line === $commentLines[1]) { + continue; + } + + // If it's empty, continue. + if (trim($tokens[$line]['content']) === '') { + continue; + } + + $commentText = ltrim($tokens[$line]['content']); + $leadingSpace = (strlen($tokens[$line]['content']) - strlen($commentText)); + + $expected = ($starColumn + 3); + if ($commentText[0] === '*') { + $expected = $starColumn; + $hasStars = true; + } + + if ($leadingSpace < $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'Comment line indented incorrectly; expected at least %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $line, 'LineIndent', $data); + if ($fix === true) { + if (isset($tokens[$line]['orig_content']) === true + && $tokens[$line]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($line, $padding.$commentText); + } + }//end if + }//end foreach + + // Finally, test the last line is correct. + $lastIndex = (count($commentLines) - 1); + $content = $tokens[$commentLines[$lastIndex]]['content']; + $commentText = ltrim($content); + if ($commentText !== '*/' && $commentText !== '**/') { + $error = 'Comment closer must be on a new line'; + $phpcsFile->addError($error, $commentLines[$lastIndex], 'CloserSameLine'); + } else { + $leadingSpace = (strlen($content) - strlen($commentText)); + + $expected = ($starColumn - 1); + if ($hasStars === true) { + $expected = $starColumn; + } + + if ($leadingSpace !== $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'Last line of comment aligned incorrectly; expected %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $commentLines[$lastIndex], 'LastLineIndent', $data); + if ($fix === true) { + if (isset($tokens[$line]['orig_content']) === true + && $tokens[$line]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($commentLines[$lastIndex], $padding.$commentText); + } + }//end if + }//end if + + // Check that the lines before and after this comment are blank. + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ((isset($tokens[$contentBefore]['scope_closer']) === true + && $tokens[$contentBefore]['scope_opener'] === $contentBefore) + || $tokens[$contentBefore]['code'] === T_OPEN_TAG + || $tokens[$contentBefore]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) !== 1) { + $error = 'Empty line not required before block comment'; + $phpcsFile->addError($error, $stackPtr, 'HasEmptyLineBefore'); + } + } else { + if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) < 2) { + $error = 'Empty line required before block comment'; + $phpcsFile->addError($error, $stackPtr, 'NoEmptyLineBefore'); + } + } + + $commentCloser = $commentLines[$lastIndex]; + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($commentCloser + 1), null, true); + if ($contentAfter !== false && ($tokens[$contentAfter]['line'] - $tokens[$commentCloser]['line']) < 2) { + $error = 'Empty line required after block comment'; + $phpcsFile->addError($error, $commentCloser, 'NoEmptyLineAfter'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 000000000..0da4ef245 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,106 @@ + + *
  • A class doc comment exists.
  • + *
  • The comment uses the correct docblock style.
  • + *
  • There are no blank lines after the class comment.
  • + *
  • No tags are used in the docblock.
  • + * + * + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[T_WHITESPACE] = T_WHITESPACE; + + $previousContent = null; + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($previousContent === null) { + $previousContent = $commentEnd; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $class = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError('Missing doc comment for class %s', $stackPtr, 'Missing', [$class]); + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes'); + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle'); + return; + } + + if ($tokens[$previousContent]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + $error = 'There must be no blank lines after the class comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfter'); + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $error = '%s tag is not allowed in class comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php new file mode 100644 index 000000000..cd509d0c8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php @@ -0,0 +1,132 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingDeclarationCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLASS, + T_INTERFACE, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens.. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_FUNCTION) { + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + + // Abstract methods do not require a closing comment. + if ($methodProps['is_abstract'] === true) { + return; + } + + // If this function is in an interface then we don't require + // a closing comment. + if ($phpcsFile->hasCondition($stackPtr, T_INTERFACE) === true) { + return; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + $error = 'Possible parse error: non-abstract method defined as abstract'; + $phpcsFile->addWarning($error, $stackPtr, 'Abstract'); + return; + } + + $decName = $phpcsFile->getDeclarationName($stackPtr); + $comment = '//end '.$decName.'()'; + } else if ($tokens[$stackPtr]['code'] === T_CLASS) { + $comment = '//end class'; + } else if ($tokens[$stackPtr]['code'] === T_INTERFACE) { + $comment = '//end interface'; + } else { + $comment = '//end enum'; + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); + return; + } + + $closingBracket = $tokens[$stackPtr]['scope_closer']; + + if ($closingBracket === null) { + // Possible inline structure. Other tests will handle it. + return; + } + + $data = [$comment]; + if (isset($tokens[($closingBracket + 1)]) === false || $tokens[($closingBracket + 1)]['code'] !== T_COMMENT) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($closingBracket + 1), null, true); + if (rtrim($tokens[$next]['content']) === $comment) { + // The comment isn't really missing; it is just in the wrong place. + $fix = $phpcsFile->addFixableError('Expected %s directly after closing brace', $closingBracket, 'Misplaced', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Just in case, because indentation fixes can add indents onto + // these comments and cause us to be unable to fix them. + $phpcsFile->fixer->replaceToken($next, $comment.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } else { + $fix = $phpcsFile->addFixableError('Expected %s', $closingBracket, 'Missing', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($closingBracket, '}'.$comment.$phpcsFile->eolChar); + } + } + + return; + }//end if + + if (rtrim($tokens[($closingBracket + 1)]['content']) !== $comment) { + $fix = $phpcsFile->addFixableError('Expected %s', $closingBracket, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closingBracket + 1), $comment.$phpcsFile->eolChar); + } + + return; + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php new file mode 100644 index 000000000..1f49d2c0c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php @@ -0,0 +1,161 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DocCommentAlignmentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOC_COMMENT_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We are only interested in function/class/interface doc block comments. + $ignore = Tokens::$emptyTokens; + if ($phpcsFile->tokenizerType === 'JS') { + $ignore[] = T_EQUAL; + $ignore[] = T_STRING; + $ignore[] = T_OBJECT_OPERATOR; + } + + $nextToken = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + $ignore = [ + T_CLASS => true, + T_INTERFACE => true, + T_ENUM => true, + T_ENUM_CASE => true, + T_FUNCTION => true, + T_PUBLIC => true, + T_PRIVATE => true, + T_PROTECTED => true, + T_STATIC => true, + T_ABSTRACT => true, + T_PROPERTY => true, + T_OBJECT => true, + T_PROTOTYPE => true, + T_VAR => true, + T_READONLY => true, + ]; + + if ($nextToken === false || isset($ignore[$tokens[$nextToken]['code']]) === false) { + // Could be a file comment. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] !== T_OPEN_TAG) { + return; + } + } + + // There must be one space after each star (unless it is an empty comment line) + // and all the stars must be aligned correctly. + $requiredColumn = ($tokens[$stackPtr]['column'] + 1); + $endComment = $tokens[$stackPtr]['comment_closer']; + for ($i = ($stackPtr + 1); $i <= $endComment; $i++) { + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STAR + && $tokens[$i]['code'] !== T_DOC_COMMENT_CLOSE_TAG + ) { + continue; + } + + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + if (trim($tokens[$i]['content']) === '') { + // Don't process an unfinished docblock close tag during live coding. + continue; + } + + // Can't process the close tag if it is not the first thing on the line. + $prev = $phpcsFile->findPrevious(T_DOC_COMMENT_WHITESPACE, ($i - 1), $stackPtr, true); + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + continue; + } + } + + if ($tokens[$i]['column'] !== $requiredColumn) { + $error = 'Expected %s space(s) before asterisk; %s found'; + $data = [ + ($requiredColumn - 1), + ($tokens[$i]['column'] - 1), + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeStar', $data); + if ($fix === true) { + $padding = str_repeat(' ', ($requiredColumn - 1)); + if ($tokens[$i]['column'] === 1) { + $phpcsFile->fixer->addContentBefore($i, $padding); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), $padding); + } + } + } + + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STAR) { + continue; + } + + if ($tokens[($i + 2)]['line'] !== $tokens[$i]['line']) { + // Line is empty. + continue; + } + + if ($tokens[($i + 1)]['code'] !== T_DOC_COMMENT_WHITESPACE) { + $error = 'Expected 1 space after asterisk; 0 found'; + $fix = $phpcsFile->addFixableError($error, $i, 'NoSpaceAfterStar'); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 2)]['code'] === T_DOC_COMMENT_TAG + && $tokens[($i + 1)]['content'] !== ' ' + ) { + $error = 'Expected 1 space after asterisk; %s found'; + $data = [$tokens[($i + 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterStar', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php new file mode 100644 index 000000000..4fc252197 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EmptyCatchCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CATCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($scopeStart + 1), $tokens[$stackPtr]['scope_closer'], true); + + if ($firstContent === false) { + $error = 'Empty CATCH statement must have a comment to explain why the exception is not handled'; + $phpcsFile->addError($error, $scopeStart, 'Missing'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 000000000..08aaae29a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,227 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FileCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + if ($tokens[$commentStart]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a file comment', $commentStart, 'WrongStyle'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + return ($phpcsFile->numTokens + 1); + } else if ($commentStart === false || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + if (isset($tokens[$commentStart]['comment_closer']) === false + || ($tokens[$tokens[$commentStart]['comment_closer']]['content'] === '' + && $tokens[$commentStart]['comment_closer'] === ($phpcsFile->numTokens - 1)) + ) { + // Don't process an unfinished file comment during live coding. + return ($phpcsFile->numTokens + 1); + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + for ($nextToken = ($commentEnd + 1); $nextToken < $phpcsFile->numTokens; $nextToken++) { + if ($tokens[$nextToken]['code'] === T_WHITESPACE) { + continue; + } + + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE + && isset($tokens[$nextToken]['attribute_closer']) === true + ) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } + + if ($nextToken === $phpcsFile->numTokens) { + $nextToken--; + } + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return ($phpcsFile->numTokens + 1); + } + + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + + // No blank line between the open tag and the file comment. + if ($tokens[$commentStart]['line'] > ($tokens[$stackPtr]['line'] + 1)) { + $error = 'There must be no blank lines before the file comment'; + $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen'); + } + + // Exactly one blank line after the file comment. + $next = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), null, true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$commentEnd]['line'] + 2)) { + $error = 'There must be exactly one blank line after the file comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfterComment'); + } + + // Required tags in correct order. + $required = [ + '@package' => true, + '@subpackage' => true, + '@author' => true, + '@copyright' => true, + ]; + + $foundTags = []; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $name = $tokens[$tag]['content']; + $isRequired = isset($required[$name]); + + if ($isRequired === true && in_array($name, $foundTags, true) === true) { + $error = 'Only one %s tag is allowed in a file comment'; + $data = [$name]; + $phpcsFile->addError($error, $tag, 'Duplicate'.ucfirst(substr($name, 1)).'Tag', $data); + } + + $foundTags[] = $name; + + if ($isRequired === false) { + continue; + } + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in file comment'; + $data = [$name]; + $phpcsFile->addError($error, $tag, 'Empty'.ucfirst(substr($name, 1)).'Tag', $data); + continue; + } + + if ($name === '@author') { + if ($tokens[$string]['content'] !== 'Squiz Pty Ltd ') { + $error = 'Expected "Squiz Pty Ltd " for author tag'; + $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectAuthor'); + if ($fix === true) { + $expected = 'Squiz Pty Ltd '; + $phpcsFile->fixer->replaceToken($string, $expected); + } + } + } else if ($name === '@copyright') { + if (preg_match('/^([0-9]{4})(-[0-9]{4})? (Squiz Pty Ltd \(ABN 77 084 670 600\))$/', $tokens[$string]['content']) === 0) { + $error = 'Expected "xxxx-xxxx Squiz Pty Ltd (ABN 77 084 670 600)" for copyright declaration'; + $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectCopyright'); + if ($fix === true) { + $matches = []; + preg_match('/^(([0-9]{4})(-[0-9]{4})?)?.*$/', $tokens[$string]['content'], $matches); + if (isset($matches[1]) === false) { + $matches[1] = date('Y'); + } + + $expected = $matches[1].' Squiz Pty Ltd (ABN 77 084 670 600)'; + $phpcsFile->fixer->replaceToken($string, $expected); + } + } + }//end if + }//end foreach + + // Check if the tags are in the correct position. + $pos = 0; + foreach ($required as $tag => $true) { + if (in_array($tag, $foundTags, true) === false) { + $error = 'Missing %s tag in file comment'; + $data = [$tag]; + $phpcsFile->addError($error, $commentEnd, 'Missing'.ucfirst(substr($tag, 1)).'Tag', $data); + } + + if (isset($foundTags[$pos]) === false) { + break; + } + + if ($foundTags[$pos] !== $tag) { + $error = 'The tag in position %s should be the %s tag'; + $data = [ + ($pos + 1), + $tag, + ]; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)).'TagOrder', $data); + } + + $pos++; + }//end foreach + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 000000000..ba3e1710f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,768 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff as PEARFunctionCommentSniff; +use PHP_CodeSniffer\Util\Common; + +class FunctionCommentSniff extends PEARFunctionCommentSniff +{ + + /** + * Whether to skip inheritdoc comments. + * + * @var boolean + */ + public $skipIfInheritdoc = false; + + /** + * The current PHP version. + * + * @var integer + */ + private $phpVersion = null; + + + /** + * Process the return comment of this function comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + $return = null; + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = in_array($methodName, $this->specialMethods, true); + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } else { + // Support both a return type and a description. + preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $content, $returnParts); + if (isset($returnParts[1]) === false) { + return; + } + + $returnType = $returnParts[1]; + + // Check return type (can be multiple, separated by '|'). + $typeNames = explode('|', $returnType); + $suggestedNames = []; + foreach ($typeNames as $i => $typeName) { + $suggestedName = Common::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames, true) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($returnType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for function return type'; + $data = [ + $suggestedType, + $returnType, + ]; + $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); + if ($fix === true) { + $replacement = $suggestedType; + if (empty($returnParts[2]) === false) { + $replacement .= $returnParts[2]; + } + + $phpcsFile->fixer->replaceToken(($return + 2), $replacement); + unset($replacement); + } + } + + // If the return type is void, make sure there is + // no return statement in the function. + if ($returnType === 'void') { + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken !== $endToken) { + // If the function is not returning anything, just + // exiting, then there is no problem. + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { + $error = 'Function return type is void, but function contains return statement'; + $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); + } + } + }//end if + } else if ($returnType !== 'mixed' && in_array('void', $typeNames, true) === false) { + // If return type is not void, there needs to be a return statement + // somewhere in the function that returns something. + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken === $endToken) { + $error = 'Function return type is not void, but function has no return statement'; + $phpcsFile->addError($error, $return, 'InvalidNoReturn'); + } else { + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] === T_SEMICOLON) { + $error = 'Function return type is not void, but function is returning void here'; + $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); + } + } + }//end if + }//end if + }//end if + } else { + if ($isSpecialMethod === true) { + return; + } + + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + $comment = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + if (isset($matches[2]) === true && trim($matches[2]) !== '') { + $comment = $matches[2]; + } + } + + if ($exception === null) { + $error = 'Exception type and comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } else if ($comment === null) { + $error = 'Comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptyThrows'); + } else { + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + } + } + + $comment = trim($comment); + + // Starts with a capital letter and ends with a fullstop. + $firstChar = $comment[0]; + if (strtoupper($firstChar) !== $firstChar) { + $error = '@throws tag comment must start with a capital letter'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); + } + + $lastChar = substr($comment, -1); + if ($lastChar !== '.') { + $error = '@throws tag comment must end with a full stop'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop'); + } + }//end if + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) + { + if ($this->phpVersion === null) { + $this->phpVersion = Config::getConfigData('php_version'); + if ($this->phpVersion === null) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + $tokens = $phpcsFile->getTokens(); + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentLines = []; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + if (empty($matches) === false) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + $commentLines[] = [ + 'comment' => $comment, + 'token' => ($tag + 2), + 'indent' => $varSpace, + ]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $indent = 0; + if ($tokens[($i - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = $tokens[($i - 1)]['length']; + } + + $comment .= ' '.$tokens[$i]['content']; + $commentLines[] = [ + 'comment' => $tokens[$i]['content'], + 'token' => $i, + 'indent' => $indent, + ]; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + $commentLines[] = ['comment' => '']; + }//end if + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'commentLines' => $commentLines, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so added + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + // If the type is empty, the whole line is empty. + if ($param['type'] === '') { + continue; + } + + // Check the param type value. + $typeNames = explode('|', $param['type']); + $suggestedTypeNames = []; + + foreach ($typeNames as $typeName) { + // Strip nullable operator. + if ($typeName[0] === '?') { + $typeName = substr($typeName, 1); + } + + $suggestedName = Common::suggestType($typeName); + $suggestedTypeNames[] = $suggestedName; + + if (count($typeNames) > 1) { + continue; + } + + // Check type hint for array and custom type. + $suggestedTypeHint = ''; + if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { + $suggestedTypeHint = 'array'; + } else if (strpos($suggestedName, 'callable') !== false) { + $suggestedTypeHint = 'callable'; + } else if (strpos($suggestedName, 'callback') !== false) { + $suggestedTypeHint = 'callable'; + } else if (in_array($suggestedName, Common::$allowedTypes, true) === false) { + $suggestedTypeHint = $suggestedName; + } + + if ($this->phpVersion >= 70000) { + if ($suggestedName === 'string') { + $suggestedTypeHint = 'string'; + } else if ($suggestedName === 'int' || $suggestedName === 'integer') { + $suggestedTypeHint = 'int'; + } else if ($suggestedName === 'float') { + $suggestedTypeHint = 'float'; + } else if ($suggestedName === 'bool' || $suggestedName === 'boolean') { + $suggestedTypeHint = 'bool'; + } + } + + if ($this->phpVersion >= 70200) { + if ($suggestedName === 'object') { + $suggestedTypeHint = 'object'; + } + } + + if ($this->phpVersion >= 80000) { + if ($suggestedName === 'mixed') { + $suggestedTypeHint = 'mixed'; + } + } + + if ($suggestedTypeHint !== '' && isset($realParams[$pos]) === true) { + $typeHint = $realParams[$pos]['type_hint']; + + // Remove namespace prefixes when comparing. + $compareTypeHint = substr($suggestedTypeHint, (strlen($typeHint) * -1)); + + if ($typeHint === '') { + $error = 'Type hint "%s" missing for %s'; + $data = [ + $suggestedTypeHint, + $param['var'], + ]; + + $errorCode = 'TypeHintMissing'; + if ($suggestedTypeHint === 'string' + || $suggestedTypeHint === 'int' + || $suggestedTypeHint === 'float' + || $suggestedTypeHint === 'bool' + ) { + $errorCode = 'Scalar'.$errorCode; + } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else if ($typeHint !== $compareTypeHint && $typeHint !== '?'.$compareTypeHint) { + $error = 'Expected type hint "%s"; found "%s" for %s'; + $data = [ + $suggestedTypeHint, + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); + }//end if + } else if ($suggestedTypeHint === '' && isset($realParams[$pos]) === true) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint !== '') { + $error = 'Unknown type hint "%s" found for %s'; + $data = [ + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); + } + }//end if + }//end foreach + + $suggestedType = implode('|', $suggestedTypeNames); + if ($param['type'] !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for parameter type'; + $data = [ + $suggestedType, + $param['type'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $suggestedType; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + if (isset($param['commentLines'][0]) === true) { + $content .= $param['commentLines'][0]['comment']; + } + + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = (strlen($param['type']) - strlen($suggestedType)); + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + // Check number of spaces after the type. + $this->checkSpacingAfterParamType($phpcsFile, $param, $maxType); + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = [ + $param['var'], + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } else if (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the var name. + $this->checkSpacingAfterParamName($phpcsFile, $param, $maxVar); + + // Param comments must start with a capital letter and end with a full stop. + if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { + $error = 'Parameter comment must start with a capital letter'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital'); + } + + $lastChar = substr($param['comment'], -1); + if ($lastChar !== '.') { + $error = 'Parameter comment must end with a full stop'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop'); + } + }//end foreach + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() + + + /** + * Check the spacing after the type of a parameter. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxType The maxlength of the longest parameter type. + * @param int $spacing The number of spaces to add after the type. + * + * @return void + */ + protected function checkSpacingAfterParamType(File $phpcsFile, $param, $maxType, $spacing=1) + { + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + $spacing); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + $diff = ($param['type_space'] - $spaces); + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + }//end checkSpacingAfterParamType() + + + /** + * Check the spacing after the name of a parameter. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxVar The maxlength of the longest parameter name. + * @param int $spacing The number of spaces to add after the type. + * + * @return void + */ + protected function checkSpacingAfterParamName(File $phpcsFile, $param, $maxVar, $spacing=1) + { + // Check number of spaces after the var name. + $spaces = ($maxVar - strlen($param['var']) + $spacing); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = ($param['var_space'] - $spaces); + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + }//end checkSpacingAfterParamName() + + + /** + * Determines whether the whole comment is an inheritdoc comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return boolean TRUE if the docblock contains only {@inheritdoc} (case-insensitive). + */ + protected function checkInheritdoc(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $allowedTokens = [ + T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + for ($i = $commentStart; $i <= $tokens[$commentStart]['comment_closer']; $i++) { + if (in_array($tokens[$i]['code'], $allowedTokens) === false) { + $trimmedContent = strtolower(trim($tokens[$i]['content'])); + + if ($trimmedContent === '{@inheritdoc}') { + return true; + } else { + return false; + } + } + } + + return false; + + }//end checkInheritdoc() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php new file mode 100644 index 000000000..a168bfe6c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php @@ -0,0 +1,233 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCommentThrowTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Abstract or incomplete. + return; + } + + $find = Tokens::$methodPrefixes; + $find[] = T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return; + } + + $stackPtrEnd = $tokens[$stackPtr]['scope_closer']; + + // Find all the exception type tokens within the current scope. + $thrownExceptions = []; + $currPos = $stackPtr; + $foundThrows = false; + $unknownCount = 0; + do { + $currPos = $phpcsFile->findNext([T_THROW, T_ANON_CLASS, T_CLOSURE], ($currPos + 1), $stackPtrEnd); + if ($currPos === false) { + break; + } + + if ($tokens[$currPos]['code'] !== T_THROW) { + $currPos = $tokens[$currPos]['scope_closer']; + continue; + } + + $foundThrows = true; + + /* + If we can't find a NEW, we are probably throwing + a variable or calling a method. + + If we're throwing a variable, and it's the same variable as the + exception container from the nearest 'catch' block, we take that exception + as it is likely to be a re-throw. + + If we can't find a matching catch block, or the variable name + is different, it's probably a different variable, so we ignore it, + but they still need to provide at least one @throws tag, even through we + don't know the exception class. + */ + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($currPos + 1), null, true); + if ($tokens[$nextToken]['code'] === T_NEW + || $tokens[$nextToken]['code'] === T_NS_SEPARATOR + || $tokens[$nextToken]['code'] === T_STRING + ) { + if ($tokens[$nextToken]['code'] === T_NEW) { + $currException = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + $currPos, + $stackPtrEnd, + false, + null, + true + ); + } else { + $currException = $nextToken; + } + + if ($currException !== false) { + $endException = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + ($currException + 1), + $stackPtrEnd, + true, + null, + true + ); + + if ($endException === false) { + $thrownExceptions[] = $tokens[$currException]['content']; + } else { + $thrownExceptions[] = $phpcsFile->getTokensAsString($currException, ($endException - $currException)); + } + }//end if + } else if ($tokens[$nextToken]['code'] === T_VARIABLE) { + // Find the nearest catch block in this scope and, if the caught var + // matches our re-thrown var, use the exception types being caught as + // exception types that are being thrown as well. + $catch = $phpcsFile->findPrevious( + T_CATCH, + $currPos, + $tokens[$stackPtr]['scope_opener'], + false, + null, + false + ); + + if ($catch !== false) { + $thrownVar = $phpcsFile->findPrevious( + T_VARIABLE, + ($tokens[$catch]['parenthesis_closer'] - 1), + $tokens[$catch]['parenthesis_opener'] + ); + + if ($tokens[$thrownVar]['content'] === $tokens[$nextToken]['content']) { + $exceptions = explode('|', $phpcsFile->getTokensAsString(($tokens[$catch]['parenthesis_opener'] + 1), ($thrownVar - $tokens[$catch]['parenthesis_opener'] - 1))); + foreach ($exceptions as $exception) { + $thrownExceptions[] = trim($exception); + } + } + } + } else { + ++$unknownCount; + }//end if + } while ($currPos < $stackPtrEnd && $currPos !== false); + + if ($foundThrows === false) { + return; + } + + // Only need one @throws tag for each type of exception thrown. + $thrownExceptions = array_unique($thrownExceptions); + + $throwTags = []; + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $exception = $tokens[($tag + 2)]['content']; + $space = strpos($exception, ' '); + if ($space !== false) { + $exception = substr($exception, 0, $space); + } + + $throwTags[$exception] = true; + } + } + + if (empty($throwTags) === true) { + $error = 'Missing @throws tag in function comment'; + $phpcsFile->addError($error, $commentEnd, 'Missing'); + return; + } else if (empty($thrownExceptions) === true) { + // If token count is zero, it means that only variables are being + // thrown, so we need at least one @throws tag (checked above). + // Nothing more to do. + return; + } + + // Make sure @throws tag count matches thrown count. + $thrownCount = (count($thrownExceptions) + $unknownCount); + $tagCount = count($throwTags); + if ($thrownCount !== $tagCount) { + $error = 'Expected %s @throws tag(s) in function comment; %s found'; + $data = [ + $thrownCount, + $tagCount, + ]; + $phpcsFile->addError($error, $commentEnd, 'WrongNumber', $data); + return; + } + + foreach ($thrownExceptions as $throw) { + if (isset($throwTags[$throw]) === true) { + continue; + } + + foreach ($throwTags as $tag => $ignore) { + if (strrpos($tag, $throw) === (strlen($tag) - strlen($throw))) { + continue 2; + } + } + + $error = 'Missing @throws tag for "%s" exception'; + $data = [$throw]; + $phpcsFile->addError($error, $commentEnd, 'Missing', $data); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php new file mode 100644 index 000000000..8ce950414 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php @@ -0,0 +1,348 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InlineCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is a function/class/interface doc block comment, skip it. + // We are only interested in inline doc block comments, which are + // not allowed. + if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + return; + } + + if ($phpcsFile->tokenizerType === 'JS') { + // We allow block comments if a function or object + // is being assigned to a variable. + $ignore = Tokens::$emptyTokens; + $ignore[] = T_EQUAL; + $ignore[] = T_STRING; + $ignore[] = T_OBJECT_OPERATOR; + $nextToken = $phpcsFile->findNext($ignore, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_FUNCTION + || $tokens[$nextToken]['code'] === T_CLOSURE + || $tokens[$nextToken]['code'] === T_OBJECT + || $tokens[$nextToken]['code'] === T_PROTOTYPE + ) { + return; + } + } + + $prevToken = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$prevToken]['code'] === T_OPEN_TAG) { + return; + } + + if ($tokens[$stackPtr]['content'] === '/**') { + $error = 'Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead'; + $phpcsFile->addError($error, $stackPtr, 'DocBlock'); + } + }//end if + + if ($tokens[$stackPtr]['content'][0] === '#') { + $error = 'Perl-style comments are not allowed; use "// Comment" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle'); + if ($fix === true) { + $comment = ltrim($tokens[$stackPtr]['content'], "# \t"); + $phpcsFile->fixer->replaceToken($stackPtr, "// $comment"); + } + } + + // We don't want end of block comments. Check if the last token before the + // comment is a closing curly brace. + $previousContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$previousContent]['line'] === $tokens[$stackPtr]['line']) { + if ($tokens[$previousContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + + // Special case for JS files. + if ($tokens[$previousContent]['code'] === T_COMMA + || $tokens[$previousContent]['code'] === T_SEMICOLON + ) { + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($previousContent - 1), null, true); + if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + } + + // Only want inline comments. + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { + return; + } + + $commentTokens = [$stackPtr]; + + $nextComment = $stackPtr; + $lastComment = $stackPtr; + while (($nextComment = $phpcsFile->findNext(T_COMMENT, ($nextComment + 1), null, false)) !== false) { + if ($tokens[$nextComment]['line'] !== ($tokens[$lastComment]['line'] + 1)) { + break; + } + + // Only want inline comments. + if (substr($tokens[$nextComment]['content'], 0, 2) !== '//') { + break; + } + + // There is a comment on the very next line. If there is + // no code between the comments, they are part of the same + // comment block. + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($nextComment - 1), $lastComment, true); + if ($prevNonWhitespace !== $lastComment) { + break; + } + + $commentTokens[] = $nextComment; + $lastComment = $nextComment; + }//end while + + $commentText = ''; + foreach ($commentTokens as $lastCommentToken) { + $comment = rtrim($tokens[$lastCommentToken]['content']); + + if (trim(substr($comment, 2)) === '') { + continue; + } + + $spaceCount = 0; + $tabFound = false; + + $commentLength = strlen($comment); + for ($i = 2; $i < $commentLength; $i++) { + if ($comment[$i] === "\t") { + $tabFound = true; + break; + } + + if ($comment[$i] !== ' ') { + break; + } + + $spaceCount++; + } + + $fix = false; + if ($tabFound === true) { + $error = 'Tab found before comment text; expected "// %s" but found "%s"'; + $data = [ + ltrim(substr($comment, 2)), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'TabBefore', $data); + } else if ($spaceCount === 0) { + $error = 'No space found before comment text; expected "// %s" but found "%s"'; + $data = [ + substr($comment, 2), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'NoSpaceBefore', $data); + } else if ($spaceCount > 1) { + $error = 'Expected 1 space before comment text but found %s; use block comment if you need indentation'; + $data = [ + $spaceCount, + substr($comment, (2 + $spaceCount)), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'SpacingBefore', $data); + }//end if + + if ($fix === true) { + $newComment = '// '.ltrim($tokens[$lastCommentToken]['content'], "/\t "); + $phpcsFile->fixer->replaceToken($lastCommentToken, $newComment); + } + + $commentText .= trim(substr($tokens[$lastCommentToken]['content'], 2)); + }//end foreach + + if ($commentText === '') { + $error = 'Blank comments are not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, ''); + } + + return ($lastCommentToken + 1); + } + + if (preg_match('/^\p{Ll}/u', $commentText) === 1) { + $error = 'Inline comments must start with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'NotCapital'); + } + + // Only check the end of comment character if the start of the comment + // is a letter, indicating that the comment is just standard text. + if (preg_match('/^\p{L}/u', $commentText) === 1) { + $commentCloser = $commentText[(strlen($commentText) - 1)]; + $acceptedClosers = [ + 'full-stops' => '.', + 'exclamation marks' => '!', + 'or question marks' => '?', + ]; + + if (in_array($commentCloser, $acceptedClosers, true) === false) { + $error = 'Inline comments must end in %s'; + $ender = ''; + foreach ($acceptedClosers as $closerName => $symbol) { + $ender .= ' '.$closerName.','; + } + + $ender = trim($ender, ' ,'); + $data = [$ender]; + $phpcsFile->addError($error, $lastCommentToken, 'InvalidEndChar', $data); + } + } + + // Finally, the line below the last comment cannot be empty if this inline + // comment is on a line by itself. + if ($tokens[$previousContent]['line'] < $tokens[$stackPtr]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($lastCommentToken + 1), null, true); + if ($next === false) { + // Ignore if the comment is the last non-whitespace token in a file. + return ($lastCommentToken + 1); + } + + if ($tokens[$next]['code'] === T_DOC_COMMENT_OPEN_TAG) { + // If this inline comment is followed by a docblock, + // ignore spacing as docblock/function etc spacing rules + // are likely to conflict with our rules. + return ($lastCommentToken + 1); + } + + $errorCode = 'SpacingAfter'; + + if (isset($tokens[$stackPtr]['conditions']) === true) { + $conditions = $tokens[$stackPtr]['conditions']; + $type = end($conditions); + $conditionPtr = key($conditions); + + if (($type === T_FUNCTION || $type === T_CLOSURE) + && $tokens[$conditionPtr]['scope_closer'] === $next + ) { + $errorCode = 'SpacingAfterAtFunctionEnd'; + } + } + + for ($i = ($lastCommentToken + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['line'] === ($tokens[$lastCommentToken]['line'] + 1)) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + return ($lastCommentToken + 1); + } + } else if ($tokens[$i]['line'] > ($tokens[$lastCommentToken]['line'] + 1)) { + break; + } + } + + $error = 'There must be no blank line following an inline comment'; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, $errorCode); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($lastCommentToken + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + return ($lastCommentToken + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php new file mode 100644 index 000000000..103d90ffb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php @@ -0,0 +1,218 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LongConditionClosingCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The openers that we are interested in. + * + * @var integer[] + */ + private static $openers = [ + T_SWITCH, + T_IF, + T_FOR, + T_FOREACH, + T_WHILE, + T_TRY, + T_CASE, + T_MATCH, + ]; + + /** + * The length that a code block must be before + * requiring a closing comment. + * + * @var integer + */ + public $lineLimit = 20; + + /** + * The format the end comment should be in. + * + * The placeholder %s will be replaced with the type of condition opener. + * + * @var string + */ + public $commentFormat = '//end %s'; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLOSE_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_condition']) === false) { + // No scope condition. It is a function closer. + return; + } + + $startCondition = $tokens[$tokens[$stackPtr]['scope_condition']]; + $startBrace = $tokens[$tokens[$stackPtr]['scope_opener']]; + $endBrace = $tokens[$stackPtr]; + + // We are only interested in some code blocks. + if (in_array($startCondition['code'], self::$openers, true) === false) { + return; + } + + if ($startCondition['code'] === T_IF) { + // If this is actually an ELSE IF, skip it as the brace + // will be checked by the original IF. + $else = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$stackPtr]['scope_condition'] - 1), null, true); + if ($tokens[$else]['code'] === T_ELSE) { + return; + } + + // IF statements that have an ELSE block need to use + // "end if" rather than "end else" or "end elseif". + do { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ELSE || $tokens[$nextToken]['code'] === T_ELSEIF) { + // Check for ELSE IF (2 tokens) as opposed to ELSEIF (1 token). + if ($tokens[$nextToken]['code'] === T_ELSE + && isset($tokens[$nextToken]['scope_closer']) === false + ) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_IF + || isset($tokens[$nextToken]['scope_closer']) === false + ) { + // Not an ELSE IF or is an inline ELSE IF. + break; + } + } + + if (isset($tokens[$nextToken]['scope_closer']) === false) { + // There isn't going to be anywhere to print the "end if" comment + // because there is no closer. + return; + } + + // The end brace becomes the ELSE's end brace. + $stackPtr = $tokens[$nextToken]['scope_closer']; + $endBrace = $tokens[$stackPtr]; + } else { + break; + }//end if + } while (isset($tokens[$nextToken]['scope_closer']) === true); + }//end if + + if ($startCondition['code'] === T_TRY) { + // TRY statements need to check until the end of all CATCH statements. + do { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_CATCH + || $tokens[$nextToken]['code'] === T_FINALLY + ) { + // The end brace becomes the CATCH end brace. + $stackPtr = $tokens[$nextToken]['scope_closer']; + $endBrace = $tokens[$stackPtr]; + } else { + break; + } + } while (isset($tokens[$nextToken]['scope_closer']) === true); + } + + if ($startCondition['code'] === T_MATCH) { + // Move the stackPtr to after the semi-colon/comma if there is one. + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextToken !== false + && ($tokens[$nextToken]['code'] === T_SEMICOLON + || $tokens[$nextToken]['code'] === T_COMMA) + ) { + $stackPtr = $nextToken; + } + } + + $lineDifference = ($endBrace['line'] - $startBrace['line']); + + $expected = sprintf($this->commentFormat, $startCondition['content']); + $comment = $phpcsFile->findNext([T_COMMENT], $stackPtr, null, false); + + if (($comment === false) || ($tokens[$comment]['line'] !== $endBrace['line'])) { + if ($lineDifference >= $this->lineLimit) { + $error = 'End comment for long condition not found; expected "%s"'; + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Missing', $data); + + if ($fix === true) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next !== false && $tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $expected .= $phpcsFile->eolChar; + } + + $phpcsFile->fixer->addContent($stackPtr, $expected); + } + } + + return; + } + + if (($comment - $stackPtr) !== 1) { + $error = 'Space found before closing comment; expected "%s"'; + $data = [$expected]; + $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data); + } + + if (trim($tokens[$comment]['content']) !== $expected) { + $found = trim($tokens[$comment]['content']); + $error = 'Incorrect closing comment; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Invalid', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($comment, $expected.$phpcsFile->eolChar); + } + + return; + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php new file mode 100644 index 000000000..ce19d5c1d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php @@ -0,0 +1,121 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class PostStatementCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * Exceptions to the rule. + * + * If post statement comments are found within the condition + * parenthesis of these structures, leave them alone. + * + * @var array + */ + private $controlStructureExceptions = [ + T_IF => true, + T_ELSEIF => true, + T_SWITCH => true, + T_WHILE => true, + T_FOR => true, + T_FOREACH => true, + T_MATCH => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { + return; + } + + $commentLine = $tokens[$stackPtr]['line']; + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($lastContent === false + || $tokens[$lastContent]['line'] !== $commentLine + || $tokens[$stackPtr]['column'] === 1 + ) { + return; + } + + if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + + // Special case for JS files and PHP closures. + if ($tokens[$lastContent]['code'] === T_COMMA + || $tokens[$lastContent]['code'] === T_SEMICOLON + ) { + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($lastContent - 1), null, true); + if ($lastContent === false || $tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + + // Special case for (trailing) comments within multi-line control structures. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + foreach ($nestedParens as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) === true + && isset($this->controlStructureExceptions[$tokens[$tokens[$open]['parenthesis_owner']]['code']]) === true + ) { + return; + } + } + } + + $error = 'Comments may not appear after statements'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($stackPtr); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php new file mode 100644 index 000000000..32e89789a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php @@ -0,0 +1,193 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; + +class VariableCommentSniff extends AbstractVariableSniff +{ + + + /** + * Called to process class member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $ignore = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_VAR => T_VAR, + T_STATIC => T_STATIC, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + T_STRING => T_STRING, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_NULLABLE => T_NULLABLE, + ]; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($commentEnd === false + || ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT) + ) { + $phpcsFile->addError('Missing member variable doc comment', $stackPtr, 'Missing'); + return; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a member variable comment', $stackPtr, 'WrongStyle'); + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + + $foundVar = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@var') { + if ($foundVar !== null) { + $error = 'Only one @var tag is allowed in a member variable comment'; + $phpcsFile->addError($error, $tag, 'DuplicateVar'); + } else { + $foundVar = $tag; + } + } else if ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in member variable comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } else { + $error = '%s tag is not allowed in member variable comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + }//end if + }//end foreach + + // The @var tag is the only one we require. + if ($foundVar === null) { + $error = 'Missing @var tag in member variable comment'; + $phpcsFile->addError($error, $commentEnd, 'MissingVar'); + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') { + $error = 'The @var tag must be the first tag in a member variable comment'; + $phpcsFile->addError($error, $foundVar, 'VarOrder'); + } + + // Make sure the tag isn't empty and has the correct padding. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) { + $error = 'Content missing for @var tag in member variable comment'; + $phpcsFile->addError($error, $foundVar, 'EmptyVar'); + return; + } + + // Support both a var type and a description. + preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $tokens[($foundVar + 2)]['content'], $varParts); + if (isset($varParts[1]) === false) { + return; + } + + $varType = $varParts[1]; + + // Check var type (can be multiple, separated by '|'). + $typeNames = explode('|', $varType); + $suggestedNames = []; + foreach ($typeNames as $i => $typeName) { + $suggestedName = Common::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames, true) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($varType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for @var tag in member variable comment'; + $data = [ + $suggestedType, + $varType, + ]; + $fix = $phpcsFile->addFixableError($error, $foundVar, 'IncorrectVarType', $data); + if ($fix === true) { + $replacement = $suggestedType; + if (empty($varParts[2]) === false) { + $replacement .= $varParts[2]; + } + + $phpcsFile->fixer->replaceToken(($foundVar + 2), $replacement); + unset($replacement); + } + } + + }//end processMemberVar() + + + /** + * Called to process a normal variable. + * + * Not required for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + + }//end processVariable() + + + /** + * Called to process variables found in double quoted strings. + * + * Not required for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100644 index 000000000..8a56b23fc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,325 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlSignatureSniff implements Sniff +{ + + /** + * How many spaces should precede the colon if using alternative syntax. + * + * @var integer + */ + public $requiredSpacesBeforeColon = 1; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return int[] + */ + public function register() + { + return [ + T_TRY, + T_CATCH, + T_FINALLY, + T_DO, + T_WHILE, + T_FOR, + T_IF, + T_FOREACH, + T_ELSE, + T_ELSEIF, + T_SWITCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + $isAlternative = false; + if (isset($tokens[$stackPtr]['scope_opener']) === true + && $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON + ) { + $isAlternative = true; + } + + // Single space after the keyword. + $expected = 1; + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false && $isAlternative === true) { + // Catching cases like: + // if (condition) : ... else: ... endif + // where there is no condition. + $expected = (int) $this->requiredSpacesBeforeColon; + } + + $found = 1; + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $found = 0; + } else if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + if (strpos($tokens[($stackPtr + 1)]['content'], $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + } + + if ($found !== $expected) { + $error = 'Expected %s space(s) after %s keyword; %s found'; + $data = [ + $expected, + strtoupper($tokens[$stackPtr]['content']), + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), str_repeat(' ', $expected)); + } + } + } + + // Single space after closing parenthesis. + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true + && isset($tokens[$stackPtr]['scope_opener']) === true + ) { + $expected = 1; + if ($isAlternative === true) { + $expected = (int) $this->requiredSpacesBeforeColon; + } + + $closer = $tokens[$stackPtr]['parenthesis_closer']; + $opener = $tokens[$stackPtr]['scope_opener']; + $content = $phpcsFile->getTokensAsString(($closer + 1), ($opener - $closer - 1)); + + if (trim($content) === '') { + if (strpos($content, $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = strlen($content); + } + } else { + $found = '"'.str_replace($phpcsFile->eolChar, '\n', $content).'"'; + } + + if ($found !== $expected) { + $error = 'Expected %s space(s) after closing parenthesis; found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceAfterCloseParenthesis', $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($closer === ($opener - 1)) { + $phpcsFile->fixer->addContent($closer, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + if (trim($content) === '') { + $phpcsFile->fixer->addContent($closer, $padding); + if ($found !== 0) { + for ($i = ($closer + 1); $i < $opener; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else { + $phpcsFile->fixer->addContent($closer, $padding.$tokens[$opener]['content']); + $phpcsFile->fixer->replaceToken($opener, ''); + + if ($tokens[$opener]['line'] !== $tokens[$closer]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$opener]['line']) { + for ($i = ($opener + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Single newline after opening brace. + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $opener = $tokens[$stackPtr]['scope_opener']; + for ($next = ($opener + 1); $next < $phpcsFile->numTokens; $next++) { + $code = $tokens[$next]['code']; + + if ($code === T_WHITESPACE + || ($code === T_INLINE_HTML + && trim($tokens[$next]['content']) === '') + ) { + continue; + } + + // Skip all empty tokens on the same line as the opener. + if ($tokens[$next]['line'] === $tokens[$opener]['line'] + && (isset(Tokens::$emptyTokens[$code]) === true + || $code === T_CLOSE_TAG) + ) { + continue; + } + + // We found the first bit of a code, or a comment on the + // following line. + break; + }//end for + + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $error = 'Newline required after opening brace'; + $fix = $phpcsFile->addFixableError($error, $opener, 'NewlineAfterOpenBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if (trim($tokens[$i]['content']) !== '') { + break; + } + + // Remove whitespace. + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContent($opener, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else if ($tokens[$stackPtr]['code'] === T_WHILE) { + // Zero spaces after parenthesis closer, but only if followed by a semicolon. + $closer = $tokens[$stackPtr]['parenthesis_closer']; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($closer + 1), null, true); + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $found = 0; + if ($tokens[($closer + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($closer + 1)]['content'], $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = $tokens[($closer + 1)]['length']; + } + } + + if ($found !== 0) { + $error = 'Expected 0 spaces before semicolon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closer + 1), ''); + } + } + } + }//end if + + // Only want to check multi-keyword structures from here on. + if ($tokens[$stackPtr]['code'] === T_WHILE) { + if (isset($tokens[$stackPtr]['scope_closer']) !== false) { + return; + } + + $closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($closer === false + || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET + || $tokens[$tokens[$closer]['scope_condition']]['code'] !== T_DO + ) { + return; + } + } else if ($tokens[$stackPtr]['code'] === T_ELSE + || $tokens[$stackPtr]['code'] === T_ELSEIF + || $tokens[$stackPtr]['code'] === T_CATCH + || $tokens[$stackPtr]['code'] === T_FINALLY + ) { + if (isset($tokens[$stackPtr]['scope_opener']) === true + && $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON + ) { + // Special case for alternate syntax, where this token is actually + // the closer for the previous block, so there is no spacing to check. + return; + } + + $closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($closer === false || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET) { + return; + } + } else { + return; + }//end if + + // Single space after closing brace. + $found = 1; + if ($tokens[($closer + 1)]['code'] !== T_WHITESPACE) { + $found = 0; + } else if ($tokens[$closer]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else if ($tokens[($closer + 1)]['content'] !== ' ') { + $found = $tokens[($closer + 1)]['length']; + } + + if ($found !== 1) { + $error = 'Expected 1 space after closing brace; %s found'; + $data = [$found]; + + if ($phpcsFile->findNext(Tokens::$commentTokens, ($closer + 1), $stackPtr) !== false) { + // Comment found between closing brace and keyword, don't auto-fix. + $phpcsFile->addError($error, $closer, 'SpaceAfterCloseBrace', $data); + return; + } + + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceAfterCloseBrace', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent($closer, ' '); + } else { + $phpcsFile->fixer->replaceToken(($closer + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100644 index 000000000..8abb8fb3c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ElseIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ELSEIF]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Usage of ELSEIF not allowed; use ELSE IF instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'else if'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php new file mode 100644 index 000000000..c5f22e23b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php @@ -0,0 +1,236 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ForEachLoopDeclarationSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOREACH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); + if ($openingBracket === false) { + $error = 'Possible parse error: FOREACH has no opening parenthesis'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingOpenParenthesis'); + return; + } + + if (isset($tokens[$openingBracket]['parenthesis_closer']) === false) { + $error = 'Possible parse error: FOREACH has no closing parenthesis'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingCloseParenthesis'); + return; + } + + $closingBracket = $tokens[$openingBracket]['parenthesis_closer']; + + if ($this->requiredSpacesAfterOpen === 0 && $tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $error = 'Space found after opening bracket of FOREACH loop'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openingBracket + 1), ''); + } + } else if ($this->requiredSpacesAfterOpen > 0) { + $spaceAfterOpen = 0; + if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openingBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openingBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openingBracket + 1), $padding); + } + } + } + }//end if + + if ($this->requiredSpacesBeforeClose === 0 && $tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $error = 'Space found before closing bracket of FOREACH loop'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closingBracket - 1), ''); + } + } else if ($this->requiredSpacesBeforeClose > 0) { + $spaceBeforeClose = 0; + if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closingBracket - 1)]['length']; + } + + if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closingBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($closingBracket - 1), $padding); + } + } + } + }//end if + + $asToken = $phpcsFile->findNext(T_AS, $openingBracket); + if ($asToken === false) { + $error = 'Possible parse error: FOREACH has no AS statement'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingAs'); + return; + } + + $content = $tokens[$asToken]['content']; + if ($content !== strtolower($content)) { + $expected = strtolower($content); + $error = 'AS keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $asToken, 'AsNotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($asToken, $expected); + } + } + + $doubleArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, $asToken, $closingBracket); + + if ($doubleArrow !== false) { + if ($tokens[($doubleArrow - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "=>"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeArrow'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($doubleArrow, ' '); + } + } else { + if ($tokens[($doubleArrow - 1)]['length'] !== 1) { + $spaces = $tokens[($doubleArrow - 1)]['length']; + $error = 'Expected 1 space before "=>"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($doubleArrow - 1), ' '); + } + } + } + + if ($tokens[($doubleArrow + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "=>"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterArrow'); + if ($fix === true) { + $phpcsFile->fixer->addContent($doubleArrow, ' '); + } + } else { + if ($tokens[($doubleArrow + 1)]['length'] !== 1) { + $spaces = $tokens[($doubleArrow + 1)]['length']; + $error = 'Expected 1 space after "=>"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($doubleArrow + 1), ' '); + } + } + } + }//end if + + if ($tokens[($asToken - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "as"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAs'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($asToken, ' '); + } + } else { + if ($tokens[($asToken - 1)]['length'] !== 1) { + $spaces = $tokens[($asToken - 1)]['length']; + $error = 'Expected 1 space before "as"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAs', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($asToken - 1), ' '); + } + } + } + + if ($tokens[($asToken + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "as"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAs'); + if ($fix === true) { + $phpcsFile->fixer->addContent($asToken, ' '); + } + } else { + if ($tokens[($asToken + 1)]['length'] !== 1) { + $spaces = $tokens[($asToken + 1)]['length']; + $error = 'Expected 1 space after "as"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($asToken + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php new file mode 100644 index 000000000..6803f9abb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php @@ -0,0 +1,316 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopDeclarationSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); + if ($openingBracket === false) { + $error = 'Possible parse error: no opening parenthesis for FOR keyword'; + $phpcsFile->addWarning($error, $stackPtr, 'NoOpenBracket'); + return; + } + + $closingBracket = $tokens[$openingBracket]['parenthesis_closer']; + + if ($this->requiredSpacesAfterOpen === 0 + && $tokens[($openingBracket + 1)]['code'] === T_WHITESPACE + ) { + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($openingBracket + 1), $closingBracket, true); + if ($this->ignoreNewlines === false + || $tokens[$nextNonWhiteSpace]['line'] === $tokens[$openingBracket]['line'] + ) { + $error = 'Whitespace found after opening bracket of FOR loop'; + $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($openingBracket + 1); $i < $closingBracket; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($this->requiredSpacesAfterOpen > 0) { + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($openingBracket + 1), $closingBracket, true); + $spaceAfterOpen = 0; + if ($tokens[$openingBracket]['line'] !== $tokens[$nextNonWhiteSpace]['line']) { + $spaceAfterOpen = 'newline'; + } else if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openingBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen + && ($this->ignoreNewlines === false + || $spaceAfterOpen !== 'newline') + ) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openingBracket, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($openingBracket + 1), $padding); + for ($i = ($openingBracket + 2); $i < $nextNonWhiteSpace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingBracket - 1), $openingBracket, true); + $beforeClosefixable = true; + if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line'] + && isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true + ) { + $beforeClosefixable = false; + } + + if ($this->requiredSpacesBeforeClose === 0 + && $tokens[($closingBracket - 1)]['code'] === T_WHITESPACE + && ($this->ignoreNewlines === false + || $tokens[$prevNonWhiteSpace]['line'] === $tokens[$closingBracket]['line']) + ) { + $error = 'Whitespace found before closing bracket of FOR loop'; + + if ($beforeClosefixable === false) { + $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose'); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket - 1); $i > $openingBracket; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($this->requiredSpacesBeforeClose > 0) { + $spaceBeforeClose = 0; + if ($tokens[$closingBracket]['line'] !== $tokens[$prevNonWhiteSpace]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closingBracket - 1)]['length']; + } + + if ($this->requiredSpacesBeforeClose !== $spaceBeforeClose + && ($this->ignoreNewlines === false + || $spaceBeforeClose !== 'newline') + ) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + + if ($beforeClosefixable === false) { + $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closingBracket, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($closingBracket - 1), $padding); + for ($i = ($closingBracket - 2); $i > $prevNonWhiteSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end if + + /* + * Check whitespace around each of the semicolon tokens. + */ + + $semicolonCount = 0; + $semicolon = $openingBracket; + $targetNestinglevel = 0; + if (isset($tokens[$openingBracket]['conditions']) === true) { + $targetNestinglevel += count($tokens[$openingBracket]['conditions']); + } + + do { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($semicolon + 1), $closingBracket); + if ($semicolon === false) { + break; + } + + if (isset($tokens[$semicolon]['conditions']) === true + && count($tokens[$semicolon]['conditions']) > $targetNestinglevel + ) { + // Semicolon doesn't belong to the for(). + continue; + } + + ++$semicolonCount; + + $humanReadableCount = 'first'; + if ($semicolonCount !== 1) { + $humanReadableCount = 'second'; + } + + $humanReadableCode = ucfirst($humanReadableCount); + $data = [$humanReadableCount]; + + // Only examine the space before the first semicolon if the first expression is not empty. + // If it *is* empty, leave it up to the `SpacingAfterOpen` logic. + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($semicolon - 1), $openingBracket, true); + if ($semicolonCount !== 1 || $prevNonWhiteSpace !== $openingBracket) { + if ($tokens[($semicolon - 1)]['code'] === T_WHITESPACE) { + $error = 'Whitespace found before %s semicolon of FOR loop'; + $errorCode = 'SpacingBefore'.$humanReadableCode; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($semicolon - 1); $i > $prevNonWhiteSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Only examine the space after the second semicolon if the last expression is not empty. + // If it *is* empty, leave it up to the `SpacingBeforeClose` logic. + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), ($closingBracket + 1), true); + if ($semicolonCount !== 2 || $nextNonWhiteSpace !== $closingBracket) { + if ($tokens[($semicolon + 1)]['code'] !== T_WHITESPACE + && $tokens[($semicolon + 1)]['code'] !== T_SEMICOLON + ) { + $error = 'Expected 1 space after %s semicolon of FOR loop; 0 found'; + $errorCode = 'NoSpaceAfter'.$humanReadableCode; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($semicolon, ' '); + } + } else if ($tokens[($semicolon + 1)]['code'] === T_WHITESPACE + && $tokens[$nextNonWhiteSpace]['code'] !== T_SEMICOLON + ) { + $spaces = $tokens[($semicolon + 1)]['length']; + if ($tokens[$semicolon]['line'] !== $tokens[$nextNonWhiteSpace]['line']) { + $spaces = 'newline'; + } + + if ($spaces !== 1 + && ($this->ignoreNewlines === false + || $spaces !== 'newline') + ) { + $error = 'Expected 1 space after %s semicolon of FOR loop; %s found'; + $errorCode = 'SpacingAfter'.$humanReadableCode; + $data[] = $spaces; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($semicolon + 1), ' '); + for ($i = ($semicolon + 2); $i < $nextNonWhiteSpace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + } while ($semicolonCount < 2); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php new file mode 100644 index 000000000..28443794a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php @@ -0,0 +1,155 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_THEN]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = null; + $closeBracket = null; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parens = $tokens[$stackPtr]['nested_parenthesis']; + $openBracket = array_pop($parens); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + + // Find the beginning of the statement. If we don't find a + // semicolon (end of statement) or comma (end of array value) + // then assume the content before the closing parenthesis is the end. + $else = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1)); + $statementEnd = $phpcsFile->findNext([T_SEMICOLON, T_COMMA], ($else + 1), $closeBracket); + if ($statementEnd === false) { + $statementEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + } + + // Make sure it's all on the same line. + if ($tokens[$statementEnd]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Inline shorthand IF statement must be declared on a single line'; + $phpcsFile->addError($error, $stackPtr, 'NotSingleLine'); + return; + } + + // Make sure there are spaces around the question mark. + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$contentBefore]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'Inline shorthand IF statement requires brackets around comparison'; + $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); + } + + $spaceBefore = ($tokens[$stackPtr]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); + if ($spaceBefore !== 1) { + $error = 'Inline shorthand IF statement requires 1 space before THEN; %s found'; + $data = [$spaceBefore]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeThen', $data); + if ($fix === true) { + if ($spaceBefore === 0) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } + + // If there is no content between the ? and the : operators, then they are + // trying to replicate an elvis operator, even though PHP doesn't have one. + // In this case, we want no spaces between the two operators so ?: looks like + // an operator itself. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_INLINE_ELSE) { + $inlineElse = $next; + if ($inlineElse !== ($stackPtr + 1)) { + $error = 'Inline shorthand IF statement without THEN statement requires 0 spaces between THEN and ELSE'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ElvisSpacing'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + } else { + $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$stackPtr]['column'] + 1)); + if ($spaceAfter !== 1) { + $error = 'Inline shorthand IF statement requires 1 space after THEN; %s found'; + $data = [$spaceAfter]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterThen', $data); + if ($fix === true) { + if ($spaceAfter === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + + // Make sure the ELSE has the correct spacing. + $inlineElse = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1), $statementEnd, false); + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($inlineElse - 1), null, true); + $spaceBefore = ($tokens[$inlineElse]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); + if ($spaceBefore !== 1) { + $error = 'Inline shorthand IF statement requires 1 space before ELSE; %s found'; + $data = [$spaceBefore]; + $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingBeforeElse', $data); + if ($fix === true) { + if ($spaceBefore === 0) { + $phpcsFile->fixer->addContentBefore($inlineElse, ' '); + } else { + $phpcsFile->fixer->replaceToken(($inlineElse - 1), ' '); + } + } + } + }//end if + + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($inlineElse + 1), null, true); + $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$inlineElse]['column'] + 1)); + if ($spaceAfter !== 1) { + $error = 'Inline shorthand IF statement requires 1 space after ELSE; %s found'; + $data = [$spaceAfter]; + $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingAfterElse', $data); + if ($fix === true) { + if ($spaceAfter === 0) { + $phpcsFile->fixer->addContent($inlineElse, ' '); + } else { + $phpcsFile->fixer->replaceToken(($inlineElse + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php new file mode 100644 index 000000000..cba076840 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercaseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSE, + T_ELSEIF, + T_FOREACH, + T_FOR, + T_DO, + T_SWITCH, + T_WHILE, + T_TRY, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php new file mode 100644 index 000000000..a5f3769db --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php @@ -0,0 +1,304 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SwitchDeclarationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SWITCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We can't process SWITCH statements unless we know where they start and end. + if (isset($tokens[$stackPtr]['scope_opener']) === false + || isset($tokens[$stackPtr]['scope_closer']) === false + ) { + return; + } + + $switch = $tokens[$stackPtr]; + $nextCase = $stackPtr; + $caseAlignment = ($switch['column'] + $this->indent); + $caseCount = 0; + $foundDefault = false; + + while (($nextCase = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], ($nextCase + 1), $switch['scope_closer'])) !== false) { + // Skip nested SWITCH statements; they are handled on their own. + if ($tokens[$nextCase]['code'] === T_SWITCH) { + $nextCase = $tokens[$nextCase]['scope_closer']; + continue; + } + + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $type = 'Default'; + $foundDefault = true; + } else { + $type = 'Case'; + $caseCount++; + } + + if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) { + $expected = strtolower($tokens[$nextCase]['content']); + $error = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $tokens[$nextCase]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'NotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($nextCase, $expected); + } + } + + if ($tokens[$nextCase]['column'] !== $caseAlignment) { + $error = strtoupper($type).' keyword must be indented '.$this->indent.' spaces from SWITCH keyword'; + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'Indent'); + + if ($fix === true) { + $padding = str_repeat(' ', ($caseAlignment - 1)); + if ($tokens[$nextCase]['column'] === 1 + || $tokens[($nextCase - 1)]['code'] !== T_WHITESPACE + ) { + $phpcsFile->fixer->addContentBefore($nextCase, $padding); + } else { + $phpcsFile->fixer->replaceToken(($nextCase - 1), $padding); + } + } + } + + if ($type === 'Case' + && ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE' + || $tokens[($nextCase + 1)]['content'] !== ' ') + ) { + $error = 'CASE keyword must be followed by a single space'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase'); + if ($fix === true) { + if ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE') { + $phpcsFile->fixer->addContent($nextCase, ' '); + } else { + $phpcsFile->fixer->replaceToken(($nextCase + 1), ' '); + } + } + } + + if (isset($tokens[$nextCase]['scope_opener']) === false) { + $error = 'Possible parse error: CASE missing opening colon'; + $phpcsFile->addWarning($error, $nextCase, 'MissingColon'); + continue; + } + + $opener = $tokens[$nextCase]['scope_opener']; + if ($tokens[($opener - 1)]['type'] === 'T_WHITESPACE') { + $error = 'There must be no space before the colon in a '.strtoupper($type).' statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon'.$type); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($opener - 1), ''); + } + } + + $nextBreak = $tokens[$nextCase]['scope_closer']; + if ($tokens[$nextBreak]['code'] === T_BREAK + || $tokens[$nextBreak]['code'] === T_RETURN + || $tokens[$nextBreak]['code'] === T_CONTINUE + || $tokens[$nextBreak]['code'] === T_THROW + || $tokens[$nextBreak]['code'] === T_EXIT + ) { + if ($tokens[$nextBreak]['scope_condition'] === $nextCase) { + // Only need to check a couple of things once, even if the + // break is shared between multiple case statements, or even + // the default case. + if ($tokens[$nextBreak]['column'] !== $caseAlignment) { + $error = 'Case breaking statement must be indented '.$this->indent.' spaces from SWITCH keyword'; + $fix = $phpcsFile->addFixableError($error, $nextBreak, 'BreakIndent'); + + if ($fix === true) { + $padding = str_repeat(' ', ($caseAlignment - 1)); + if ($tokens[$nextBreak]['column'] === 1 + || $tokens[($nextBreak - 1)]['code'] !== T_WHITESPACE + ) { + $phpcsFile->fixer->addContentBefore($nextBreak, $padding); + } else { + $phpcsFile->fixer->replaceToken(($nextBreak - 1), $padding); + } + } + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextBreak - 1), $stackPtr, true); + if ($tokens[$prev]['line'] !== ($tokens[$nextBreak]['line'] - 1)) { + $error = 'Blank lines are not allowed before case breaking statements'; + $phpcsFile->addError($error, $nextBreak, 'SpacingBeforeBreak'); + } + + $nextLine = $tokens[$tokens[$stackPtr]['scope_closer']]['line']; + $semicolon = $phpcsFile->findEndOfStatement($nextBreak); + for ($i = ($semicolon + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $nextLine = $tokens[$i]['line']; + break; + } + } + + if ($type === 'Case') { + // Ensure the BREAK statement is followed by + // a single blank line, or the end switch brace. + if ($nextLine !== ($tokens[$semicolon]['line'] + 2) && $i !== $tokens[$stackPtr]['scope_closer']) { + $error = 'Case breaking statements must be followed by a single blank line'; + $fix = $phpcsFile->addFixableError($error, $nextBreak, 'SpacingAfterBreak'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($semicolon + 1); $i <= $tokens[$stackPtr]['scope_closer']; $i++) { + if ($tokens[$i]['line'] === $nextLine) { + $phpcsFile->fixer->addNewlineBefore($i); + break; + } + + if ($tokens[$i]['line'] === $tokens[$semicolon]['line']) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else { + // Ensure the BREAK statement is not followed by a blank line. + if ($nextLine !== ($tokens[$semicolon]['line'] + 1)) { + $error = 'Blank lines are not allowed after the DEFAULT case\'s breaking statement'; + $phpcsFile->addError($error, $nextBreak, 'SpacingAfterDefaultBreak'); + } + }//end if + + $caseLine = $tokens[$nextCase]['line']; + $nextLine = $tokens[$nextBreak]['line']; + for ($i = ($opener + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $nextLine = $tokens[$i]['line']; + break; + } + } + + if ($nextLine !== ($caseLine + 1)) { + $error = 'Blank lines are not allowed after '.strtoupper($type).' statements'; + $phpcsFile->addError($error, $nextCase, 'SpacingAfter'.$type); + } + }//end if + + if ($tokens[$nextBreak]['code'] === T_BREAK) { + if ($type === 'Case') { + // Ensure empty CASE statements are not allowed. + // They must have some code content in them. A comment is not enough. + // But count RETURN statements as valid content if they also + // happen to close the CASE statement. + $foundContent = false; + for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['code'] === T_CASE) { + $i = $tokens[$i]['scope_opener']; + continue; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $foundContent = true; + break; + } + } + + if ($foundContent === false) { + $error = 'Empty CASE statements are not allowed'; + $phpcsFile->addError($error, $nextCase, 'EmptyCase'); + } + } else { + // Ensure empty DEFAULT statements are not allowed. + // They must (at least) have a comment describing why + // the default case is being ignored. + $foundContent = false; + for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $foundContent = true; + break; + } + } + + if ($foundContent === false) { + $error = 'Comment required for empty DEFAULT case'; + $phpcsFile->addError($error, $nextCase, 'EmptyDefault'); + } + }//end if + }//end if + } else if ($type === 'Default') { + $error = 'DEFAULT case must have a breaking statement'; + $phpcsFile->addError($error, $nextCase, 'DefaultNoBreak'); + }//end if + }//end while + + if ($foundDefault === false) { + $error = 'All SWITCH statements must contain a DEFAULT case'; + $phpcsFile->addError($error, $stackPtr, 'MissingDefault'); + } + + if ($tokens[$switch['scope_closer']]['column'] !== $switch['column']) { + $error = 'Closing brace of SWITCH statement must be aligned with SWITCH keyword'; + $phpcsFile->addError($error, $switch['scope_closer'], 'CloseBraceAlign'); + } + + if ($caseCount === 0) { + $error = 'SWITCH statements must contain at least one CASE statement'; + $phpcsFile->addError($error, $stackPtr, 'MissingCase'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php new file mode 100644 index 000000000..49dfc2c42 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JSLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jslint.js could not be run + */ + public function process(File $phpcsFile, $stackPtr) + { + $rhinoPath = Config::getExecutablePath('rhino'); + $jslintPath = Config::getExecutablePath('jslint'); + if ($rhinoPath === null || $jslintPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $rhinoPath = Common::escapeshellcmd($rhinoPath); + $jslintPath = Common::escapeshellcmd($jslintPath); + + $cmd = "$rhinoPath \"$jslintPath\" ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + if (is_array($output) === true) { + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match('/Lint at line ([0-9]+).*:(.*)$/', $finding, $matches); + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches[1]; + $message = 'jslint says: '.trim($matches[2]); + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php new file mode 100644 index 000000000..30dca6722 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JavaScriptLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If Javascript Lint ran into trouble. + */ + public function process(File $phpcsFile, $stackPtr) + { + $jslPath = Config::getExecutablePath('jsl'); + if ($jslPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + $cmd = '"'.Common::escapeshellcmd($jslPath).'" -nologo -nofilelisting -nocontext -nosummary -output-format __LINE__:__ERROR__ -process '.escapeshellarg($fileName); + $msg = exec($cmd, $output, $retval); + + // Variable $exitCode is the last line of $output if no error occurs, on + // error it is numeric. Try to handle various error conditions and + // provide useful error reporting. + if ($retval === 2 || $retval === 4) { + if (is_array($output) === true) { + $msg = join('\n', $output); + } + + throw new RuntimeException("Failed invoking JavaScript Lint, retval was [$retval], output was [$msg]"); + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + $split = strpos($finding, ':'); + $line = substr($finding, 0, $split); + $message = substr($finding, ($split + 1)); + $phpcsFile->addWarningOnLine(trim($message), $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php new file mode 100644 index 000000000..6277b809e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FileExtensionSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $fileName = $phpcsFile->getFilename(); + $extension = substr($fileName, strrpos($fileName, '.')); + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], $stackPtr); + + if ($nextClass !== false) { + $phpcsFile->recordMetric($stackPtr, 'File extension for class files', $extension); + if ($extension === '.php') { + $error = '%s found in ".php" file; use ".inc" extension instead'; + $data = [ucfirst($tokens[$nextClass]['content'])]; + $phpcsFile->addError($error, $stackPtr, 'ClassFound', $data); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'File extension for non-class files', $extension); + if ($extension === '.inc') { + $error = 'No interface or class found in ".inc" file; use ".php" extension instead'; + $phpcsFile->addError($error, $stackPtr, 'NoClass'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php new file mode 100644 index 000000000..60b113d3a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php @@ -0,0 +1,393 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorBracketSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$operators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$stackPtr]['code'] === T_PLUS) { + // JavaScript uses the plus operator for string concatenation as well + // so we cannot accurately determine if it is a string concat or addition. + // So just ignore it. + return; + } + + // If the & is a reference, then we don't want to check for brackets. + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr) === true) { + return; + } + + // There is one instance where brackets aren't needed, which involves + // the minus sign being used to assign a negative number to a variable. + if ($tokens[$stackPtr]['code'] === T_MINUS) { + // Check to see if we are trying to return -n. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_RETURN) { + return; + } + + $number = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$number]['code'] === T_LNUMBER || $tokens[$number]['code'] === T_DNUMBER) { + $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($previous !== false) { + $isAssignment = isset(Tokens::$assignmentTokens[$tokens[$previous]['code']]); + $isEquality = isset(Tokens::$equalityTokens[$tokens[$previous]['code']]); + $isComparison = isset(Tokens::$comparisonTokens[$tokens[$previous]['code']]); + $isUnary = isset(Tokens::$operators[$tokens[$previous]['code']]); + if ($isAssignment === true || $isEquality === true || $isComparison === true || $isUnary === true) { + // This is a negative assignment or comparison. + // We need to check that the minus and the number are + // adjacent. + if (($number - $stackPtr) !== 1) { + $error = 'No space allowed between minus sign and number'; + $phpcsFile->addError($error, $stackPtr, 'SpacingAfterMinus'); + } + + return; + } + } + } + }//end if + + $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true, null, true); + if ($previousToken !== false) { + // A list of tokens that indicate that the token is not + // part of an arithmetic operation. + $invalidTokens = [ + T_COMMA => true, + T_COLON => true, + T_OPEN_PARENTHESIS => true, + T_OPEN_SQUARE_BRACKET => true, + T_OPEN_CURLY_BRACKET => true, + T_OPEN_SHORT_ARRAY => true, + T_CASE => true, + T_EXIT => true, + ]; + + if (isset($invalidTokens[$tokens[$previousToken]['code']]) === true) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_OR + && isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $brackets = $tokens[$stackPtr]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if (isset($tokens[$lastBracket]['parenthesis_owner']) === true + && $tokens[$tokens[$lastBracket]['parenthesis_owner']]['code'] === T_CATCH + ) { + // This is a pipe character inside a catch statement, so it is acting + // as an exception type separator and not an arithmetic operation. + return; + } + } + + // Tokens that are allowed inside a bracketed operation. + $allowed = [ + T_VARIABLE, + T_LNUMBER, + T_DNUMBER, + T_STRING, + T_WHITESPACE, + T_NS_SEPARATOR, + T_THIS, + T_SELF, + T_STATIC, + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + T_MODULUS, + T_NONE, + T_BITWISE_NOT, + ]; + + $allowed += Tokens::$operators; + + $lastBracket = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true); + foreach ($parenthesis as $bracket => $endBracket) { + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($bracket - 1), null, true); + $prevCode = $tokens[$prevToken]['code']; + + if ($prevCode === T_ISSET) { + // This operation is inside an isset() call, but has + // no bracket of it's own. + break; + } + + if ($prevCode === T_STRING || $prevCode === T_SWITCH || $prevCode === T_MATCH) { + // We allow simple operations to not be bracketed. + // For example, ceil($one / $two). + for ($prev = ($stackPtr - 1); $prev > $bracket; $prev--) { + if (in_array($tokens[$prev]['code'], $allowed, true) === true) { + continue; + } + + if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { + $prev = $tokens[$prev]['parenthesis_opener']; + } else { + break; + } + } + + if ($prev !== $bracket) { + break; + } + + for ($next = ($stackPtr + 1); $next < $endBracket; $next++) { + if (in_array($tokens[$next]['code'], $allowed, true) === true) { + continue; + } + + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + $next = $tokens[$next]['parenthesis_closer']; + } else { + break; + } + } + + if ($next !== $endBracket) { + break; + } + }//end if + + if (in_array($prevCode, Tokens::$scopeOpeners, true) === true) { + // This operation is inside a control structure like FOREACH + // or IF, but has no bracket of it's own. + // The only control structures allowed to do this are SWITCH and MATCH. + if ($prevCode !== T_SWITCH && $prevCode !== T_MATCH) { + break; + } + } + + if ($prevCode === T_OPEN_PARENTHESIS) { + // These are two open parenthesis in a row. If the current + // one doesn't enclose the operator, go to the previous one. + if ($endBracket < $stackPtr) { + continue; + } + } + + $lastBracket = $bracket; + break; + }//end foreach + }//end if + + if ($lastBracket === false) { + // It is not in a bracketed statement at all. + $this->addMissingBracketsError($phpcsFile, $stackPtr); + return; + } else if ($tokens[$lastBracket]['parenthesis_closer'] < $stackPtr) { + // There are a set of brackets in front of it that don't include it. + $this->addMissingBracketsError($phpcsFile, $stackPtr); + return; + } else { + // We are enclosed in a set of bracket, so the last thing to + // check is that we are not also enclosed in square brackets + // like this: ($array[$index + 1]), which is invalid. + $brackets = [ + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + ]; + + $squareBracket = $phpcsFile->findPrevious($brackets, ($stackPtr - 1), $lastBracket); + if ($squareBracket !== false && $tokens[$squareBracket]['code'] === T_OPEN_SQUARE_BRACKET) { + $closeSquareBracket = $phpcsFile->findNext($brackets, ($stackPtr + 1)); + if ($closeSquareBracket !== false && $tokens[$closeSquareBracket]['code'] === T_CLOSE_SQUARE_BRACKET) { + $this->addMissingBracketsError($phpcsFile, $stackPtr); + } + } + + return; + }//end if + + $lastAssignment = $phpcsFile->findPrevious(Tokens::$assignmentTokens, $stackPtr, null, false, null, true); + if ($lastAssignment !== false && $lastAssignment > $lastBracket) { + $this->addMissingBracketsError($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Add and fix the missing brackets error. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function addMissingBracketsError($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $allowed = [ + T_VARIABLE => true, + T_LNUMBER => true, + T_DNUMBER => true, + T_STRING => true, + T_CONSTANT_ENCAPSED_STRING => true, + T_DOUBLE_QUOTED_STRING => true, + T_WHITESPACE => true, + T_NS_SEPARATOR => true, + T_THIS => true, + T_SELF => true, + T_STATIC => true, + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_DOUBLE_COLON => true, + T_MODULUS => true, + T_ISSET => true, + T_ARRAY => true, + T_NONE => true, + T_BITWISE_NOT => true, + ]; + + // Find the first token in the expression. + for ($before = ($stackPtr - 1); $before > 0; $before--) { + // Special case for plus operators because we can't tell if they are used + // for addition or string contact. So assume string concat to be safe. + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$before]['code'] === T_PLUS) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$before]['code']]) === true + || isset(Tokens::$operators[$tokens[$before]['code']]) === true + || isset(Tokens::$castTokens[$tokens[$before]['code']]) === true + || isset($allowed[$tokens[$before]['code']]) === true + ) { + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_PARENTHESIS) { + $before = $tokens[$before]['parenthesis_opener']; + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_SQUARE_BRACKET) { + $before = $tokens[$before]['bracket_opener']; + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_SHORT_ARRAY) { + $before = $tokens[$before]['bracket_opener']; + continue; + } + + break; + }//end for + + $before = $phpcsFile->findNext(Tokens::$emptyTokens, ($before + 1), null, true); + + // A few extra tokens are allowed to be on the right side of the expression. + $allowed[T_EQUAL] = true; + $allowed[T_NEW] = true; + + // Find the last token in the expression. + for ($after = ($stackPtr + 1); $after < $phpcsFile->numTokens; $after++) { + // Special case for plus operators because we can't tell if they are used + // for addition or string concat. So assume string concat to be safe. + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$after]['code'] === T_PLUS) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$after]['code']]) === true + || isset(Tokens::$operators[$tokens[$after]['code']]) === true + || isset(Tokens::$castTokens[$tokens[$after]['code']]) === true + || isset($allowed[$tokens[$after]['code']]) === true + ) { + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_PARENTHESIS) { + $after = $tokens[$after]['parenthesis_closer']; + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_SQUARE_BRACKET) { + $after = $tokens[$after]['bracket_closer']; + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_SHORT_ARRAY) { + $after = $tokens[$after]['bracket_closer']; + continue; + } + + break; + }//end for + + $after = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($after - 1), null, true); + + $error = 'Operation must be bracketed'; + if ($before === $after || $before === $stackPtr || $after === $stackPtr) { + $phpcsFile->addError($error, $stackPtr, 'MissingBrackets'); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingBrackets'); + if ($fix === true) { + // Can only fix this error if both tokens are available for fixing. + // Adding one bracket without the other will create parse errors. + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($before, '('.$tokens[$before]['content']); + $phpcsFile->fixer->replaceToken($after, $tokens[$after]['content'].')'); + $phpcsFile->fixer->endChangeset(); + } + + }//end addMissingBracketsError() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php new file mode 100644 index 000000000..e696d8001 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php @@ -0,0 +1,398 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionDeclarationArgumentSpacingSniff implements Sniff +{ + + /** + * How many spaces should surround the equals signs. + * + * @var integer + */ + public $equalsSpacing = 0; + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $this->equalsSpacing = (int) $this->equalsSpacing; + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + + $this->processBracket($phpcsFile, $tokens[$stackPtr]['parenthesis_opener']); + + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null); + $this->processBracket($phpcsFile, $openBracket); + } + } + + }//end process() + + + /** + * Processes the contents of a single set of brackets. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $openBracket The position of the open bracket + * in the stack. + * + * @return void + */ + public function processBracket($phpcsFile, $openBracket) + { + $tokens = $phpcsFile->getTokens(); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $multiLine = ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']); + + if (isset($tokens[$openBracket]['parenthesis_owner']) === true) { + $stackPtr = $tokens[$openBracket]['parenthesis_owner']; + } else { + $stackPtr = $phpcsFile->findPrevious(T_USE, ($openBracket - 1)); + } + + $params = $phpcsFile->getMethodParameters($stackPtr); + + if (empty($params) === true) { + // Check spacing around parenthesis. + $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closeBracket, true); + if ($next === false) { + if (($closeBracket - $openBracket) !== 1) { + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($openBracket + 1)]['length']; + } + + $error = 'Expected 0 spaces between parenthesis of function declaration; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingBetween', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + + // No params, so we don't check normal spacing rules. + return; + } + }//end if + + foreach ($params as $paramNumber => $param) { + if ($param['pass_by_reference'] === true) { + $refToken = $param['reference_token']; + + $gap = 0; + if ($tokens[($refToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($refToken + 1)]['length']; + } + + if ($gap !== 0) { + $error = 'Expected 0 spaces after reference operator for argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $refToken, 'SpacingAfterReference', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($refToken + 1), ''); + } + } + }//end if + + if ($param['variable_length'] === true) { + $variadicToken = $param['variadic_token']; + + $gap = 0; + if ($tokens[($variadicToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($variadicToken + 1)]['length']; + } + + if ($gap !== 0) { + $error = 'Expected 0 spaces after variadic operator for argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $variadicToken, 'SpacingAfterVariadic', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($variadicToken + 1), ''); + } + } + }//end if + + if (isset($param['default_equal_token']) === true) { + $equalToken = $param['default_equal_token']; + + $spacesBefore = 0; + if (($equalToken - $param['token']) > 1) { + $spacesBefore = $tokens[($param['token'] + 1)]['length']; + } + + if ($spacesBefore !== $this->equalsSpacing) { + $error = 'Incorrect spacing between argument "%s" and equals sign; expected '.$this->equalsSpacing.' but found %s'; + $data = [ + $param['name'], + $spacesBefore, + ]; + + $fix = $phpcsFile->addFixableError($error, $equalToken, 'SpaceBeforeEquals', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->equalsSpacing); + if ($spacesBefore === 0) { + $phpcsFile->fixer->addContentBefore($equalToken, $padding); + } else { + $phpcsFile->fixer->replaceToken(($equalToken - 1), $padding); + } + } + }//end if + + $spacesAfter = 0; + if ($tokens[($equalToken + 1)]['code'] === T_WHITESPACE) { + $spacesAfter = $tokens[($equalToken + 1)]['length']; + } + + if ($spacesAfter !== $this->equalsSpacing) { + $error = 'Incorrect spacing between default value and equals sign for argument "%s"; expected '.$this->equalsSpacing.' but found %s'; + $data = [ + $param['name'], + $spacesAfter, + ]; + + $fix = $phpcsFile->addFixableError($error, $equalToken, 'SpaceAfterEquals', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->equalsSpacing); + if ($spacesAfter === 0) { + $phpcsFile->fixer->addContent($equalToken, $padding); + } else { + $phpcsFile->fixer->replaceToken(($equalToken + 1), $padding); + } + } + }//end if + }//end if + + if ($param['type_hint_token'] !== false) { + $typeHintToken = $param['type_hint_end_token']; + + $gap = 0; + if ($tokens[($typeHintToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($typeHintToken + 1)]['length']; + } + + if ($gap !== 1) { + $error = 'Expected 1 space between type hint and argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $typeHintToken, 'SpacingAfterHint', $data); + if ($fix === true) { + if ($gap === 0) { + $phpcsFile->fixer->addContent($typeHintToken, ' '); + } else { + $phpcsFile->fixer->replaceToken(($typeHintToken + 1), ' '); + } + } + } + }//end if + + $commaToken = false; + if ($paramNumber > 0 && $params[($paramNumber - 1)]['comma_token'] !== false) { + $commaToken = $params[($paramNumber - 1)]['comma_token']; + } + + if ($commaToken !== false) { + if ($tokens[($commaToken - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected 0 spaces between argument "%s" and comma; %s found'; + $data = [ + $params[($paramNumber - 1)]['name'], + $tokens[($commaToken - 1)]['length'], + ]; + + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken - 1), ''); + } + } + + // Don't check spacing after the comma if it is the last content on the line. + $checkComma = true; + if ($multiLine === true) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($commaToken + 1), $closeBracket, true); + if ($tokens[$next]['line'] !== $tokens[$commaToken]['line']) { + $checkComma = false; + } + } + + if ($checkComma === true) { + if ($param['type_hint_token'] === false) { + $spacesAfter = 0; + if ($tokens[($commaToken + 1)]['code'] === T_WHITESPACE) { + $spacesAfter = $tokens[($commaToken + 1)]['length']; + } + + if ($spacesAfter === 0) { + $error = 'Expected 1 space between comma and argument "%s"; 0 found'; + $data = [$param['name']]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'NoSpaceBeforeArg', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($commaToken, ' '); + } + } else if ($spacesAfter !== 1) { + $error = 'Expected 1 space between comma and argument "%s"; %s found'; + $data = [ + $param['name'], + $spacesAfter, + ]; + + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpacingBeforeArg', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken + 1), ' '); + } + }//end if + } else { + $hint = $phpcsFile->getTokensAsString($param['type_hint_token'], (($param['type_hint_end_token'] - $param['type_hint_token']) + 1)); + if ($param['nullable_type'] === true) { + $hint = '?'.$hint; + } + + if ($tokens[($commaToken + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space between comma and type hint "%s"; 0 found'; + $data = [$hint]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'NoSpaceBeforeHint', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($commaToken, ' '); + } + } else { + $gap = $tokens[($commaToken + 1)]['length']; + if ($gap !== 1) { + $error = 'Expected 1 space between comma and type hint "%s"; %s found'; + $data = [ + $hint, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpacingBeforeHint', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken + 1), ' '); + } + } + }//end if + }//end if + }//end if + }//end if + }//end foreach + + // Only check spacing around parenthesis for single line definitions. + if ($multiLine === true) { + return; + } + + $gap = 0; + if ($tokens[($closeBracket - 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($closeBracket - 1)]['length']; + } + + if ($gap !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing parenthesis; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpacingBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($gap === 0) { + $phpcsFile->fixer->addContentBefore($closeBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket - 1), $padding); + } + } + } + + $gap = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($openBracket + 1)]['length']; + } + + if ($gap !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening parenthesis; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($gap === 0) { + $phpcsFile->fixer->addContent($openBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), $padding); + } + } + } + + }//end processBracket() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php new file mode 100644 index 000000000..4b6a6acfd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php @@ -0,0 +1,34 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Sniffs\AbstractPatternSniff; + +class FunctionDeclarationSniff extends AbstractPatternSniff +{ + + + /** + * Returns an array of patterns to check are correct. + * + * @return array + */ + protected function getPatterns() + { + return [ + 'function abc(...);', + 'function abc(...)', + 'abstract function abc(...);', + ]; + + }//end getPatterns() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php new file mode 100644 index 000000000..f6fc383ae --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionDuplicateArgumentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $foundVariables = []; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + $variable = $tokens[$i]['content']; + if (in_array($variable, $foundVariables, true) === true) { + $error = 'Variable "%s" appears more than once in function declaration'; + $data = [$variable]; + $phpcsFile->addError($error, $i, 'Found', $data); + } else { + $foundVariables[] = $variable; + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php new file mode 100644 index 000000000..24588a912 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class GlobalFunctionSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + return; + } + + // Special exception for __autoload as it needs to be global. + if ($functionName !== '__autoload') { + $error = 'Consider putting global function "%s" in a static class'; + $data = [$functionName]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php new file mode 100644 index 000000000..2357960c2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercaseFunctionKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$methodPrefixes; + $tokens[] = T_FUNCTION; + $tokens[] = T_CLOSURE; + $tokens[] = T_FN; + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php new file mode 100644 index 000000000..c12bd0c47 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php @@ -0,0 +1,258 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionDeclarationSniff as PEARFunctionDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultiLineFunctionDeclarationSniff extends PEARFunctionDeclarationSniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Determine if this is a multi-line function declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) + { + $bracketsToCheck = [$stackPtr => $openBracket]; + + // Closures may use the USE keyword and so be multi-line in this way. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($tokens[$openBracket]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + if ($open !== false) { + $bracketsToCheck[$use] = $open; + } + } + } + + foreach ($bracketsToCheck as $stackPtr => $openBracket) { + // If the first argument is on a new line, this is a multi-line + // function declaration, even if there is only one argument. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + return true; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $end = $phpcsFile->findEndOfStatement($openBracket + 1); + while ($tokens[$end]['code'] === T_COMMA) { + // If the next bit of code is not on the same line, this is a + // multi-line function declaration. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next === false) { + continue(2); + } + + if ($tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + $end = $phpcsFile->findEndOfStatement($next); + } + + // We've reached the last argument, so see if the next content + // (should be the close bracket) is also on the same line. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + }//end foreach + + return false; + + }//end isMultiLineDeclaration() + + + /** + * Processes single-line declarations. + * + * Just uses the Generic BSD-Allman brace sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + // We do everything the parent sniff does, and a bit more because we + // define multi-line declarations a bit differently. + parent::processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens); + + $openingBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closingBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingBracket - 1), $openingBracket, true); + if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line']) { + $error = 'There must not be a newline before the closing parenthesis of a single-line function declaration'; + + if (isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true) { + $phpcsFile->addError($error, $closingBracket, 'CloseBracketNewLine'); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'CloseBracketNewLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket - 1); $i > $openingBracket; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processSingleLineDeclaration() + + + /** + * Processes multi-line declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + // We do everything the parent sniff does, and a bit more. + parent::processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $this->processBracket($phpcsFile, $openBracket, $tokens, 'function'); + + if ($tokens[$stackPtr]['code'] !== T_CLOSURE) { + return; + } + + $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use === false) { + return; + } + + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null); + $this->processBracket($phpcsFile, $openBracket, $tokens, 'use'); + + }//end processMultiLineDeclaration() + + + /** + * Processes the contents of a single set of brackets. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $openBracket The position of the open bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * @param string $type The type of the token the brackets + * belong to (function or use). + * + * @return void + */ + public function processBracket($phpcsFile, $openBracket, $tokens, $type='function') + { + $errorPrefix = ''; + if ($type === 'use') { + $errorPrefix = 'Use'; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + // The open bracket should be the last thing on the line. + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $error = 'The first parameter of a multi-line '.$type.' declaration must be on the line after the opening bracket'; + $fix = $phpcsFile->addFixableError($error, $next, $errorPrefix.'FirstParamSpacing'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $phpcsFile->fixer->addNewline($openBracket); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($x = $openBracket; $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$openBracket]['line']) { + continue; + } + + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + break; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + // Each line between the brackets should contain a single parameter. + $lastComma = null; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + // Skip brackets, like arrays, as they can contain commas. + if (isset($tokens[$i]['bracket_opener']) === true) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if (isset($tokens[$i]['parenthesis_opener']) === true) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$i]['line']) { + $error = 'Multi-line '.$type.' declarations must define one parameter per line'; + $fix = $phpcsFile->addFixableError($error, $next, $errorPrefix.'OneParamPerLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($i); + } + } + }//end for + + }//end processBracket() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 000000000..878035e67 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff as PEARValidFunctionNameSniff; +use PHP_CodeSniffer\Util\Common; + +class ValidFunctionNameSniff extends PEARValidFunctionNameSniff +{ + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + return; + } + + $errorData = [$functionName]; + + // Does this function claim to be magical? + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'DoubleUnderscore', $errorData); + + $functionName = ltrim($functionName, '_'); + } + + if (Common::isCamelCaps($functionName, false, true, false) === false) { + $error = 'Function name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..5c3a74930 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,190 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + return; + } + + $objOperator = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR + || $tokens[$objOperator]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Check to see if we are using a variable from an object. + $var = $phpcsFile->findNext([T_WHITESPACE], ($objOperator + 1), null, true); + if ($tokens[$var]['code'] === T_STRING) { + $bracket = $phpcsFile->findNext([T_WHITESPACE], ($var + 1), null, true); + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + $objVarName = $tokens[$var]['content']; + + // There is no way for us to know if the var is public or + // private, so we have to ignore a leading underscore if there is + // one and just check the main part of the variable name. + $originalVarName = $objVarName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $var, 'MemberNotCamelCaps', $data); + } + }//end if + }//end if + }//end if + + $objOperator = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $objVarName = $varName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $data); + } + + return; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $inClass = $phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + if ($inClass === true) { + $varName = substr($varName, 1); + } + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } + + }//end processVariable() + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + // Couldn't get any info about this variable, which + // generally means it is invalid or possibly has a parse + // error. Any errors will be reported by the core, so + // we can ignore it. + return; + } + + $public = ($memberProps['scope'] !== 'private'); + $errorData = [$varName]; + + if ($public === true) { + if (substr($varName, 0, 1) === '_') { + $error = '%s member variable "%s" must not contain a leading underscore'; + $data = [ + ucfirst($memberProps['scope']), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); + } + } else { + if (substr($varName, 0, 1) !== '_') { + $error = 'Private member variable "%s" must contain a leading underscore'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + } + } + + // Remove a potential underscore prefix for testing CamelCaps. + $varName = ltrim($varName, '_'); + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $errorData); + } + + }//end processMemberVar() + + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match_all('|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + continue; + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'StringNotCamelCaps', $data); + } + } + } + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php new file mode 100644 index 000000000..c324e2058 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowObjectStringIndexSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_SQUARE_BRACKET]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check if the next non whitespace token is a string. + $index = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$index]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + // Make sure it is the only thing in the square brackets. + $next = $phpcsFile->findNext(T_WHITESPACE, ($index + 1), null, true); + if ($tokens[$next]['code'] !== T_CLOSE_SQUARE_BRACKET) { + return; + } + + // Allow indexes that have dots in them because we can't write + // them in dot notation. + $content = trim($tokens[$index]['content'], '"\' '); + if (strpos($content, '.') !== false) { + return; + } + + // Also ignore reserved words. + if ($content === 'super') { + return; + } + + // Token before the opening square bracket cannot be a var name. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_STRING) { + $error = 'Object indexes must be written in dot notation'; + $phpcsFile->addError($error, $prev, 'Found'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php new file mode 100644 index 000000000..84facf054 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ObjectInstantiationSniff implements Sniff +{ + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $allowedTokens = Tokens::$emptyTokens; + $allowedTokens[] = T_BITWISE_AND; + + $prev = $phpcsFile->findPrevious($allowedTokens, ($stackPtr - 1), null, true); + + $allowedTokens = [ + T_EQUAL => T_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_FN_ARROW => T_FN_ARROW, + T_MATCH_ARROW => T_MATCH_ARROW, + T_THROW => T_THROW, + T_RETURN => T_RETURN, + ]; + + if (isset($allowedTokens[$tokens[$prev]['code']]) === true) { + return; + } + + $ternaryLikeTokens = [ + T_COALESCE => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + // For ternary like tokens, walk a little further back to see if it is preceded by + // one of the allowed tokens (within the same statement). + if (isset($ternaryLikeTokens[$tokens[$prev]['code']]) === true) { + $hasAllowedBefore = $phpcsFile->findPrevious($allowedTokens, ($prev - 1), null, false, null, true); + if ($hasAllowedBefore !== false) { + return; + } + } + + $error = 'New objects must be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'NotAssigned'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php new file mode 100644 index 000000000..787d3fc82 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ObjectMemberCommaSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [T_CLOSE_OBJECT]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_COMMA) { + $error = 'Last member of object must not be followed by a comma'; + $fix = $phpcsFile->addFixableError($error, $prev, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php new file mode 100644 index 000000000..85e9825f8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php @@ -0,0 +1,235 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ComparisonOperatorUsageSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * A list of valid comparison operators. + * + * @var array + */ + private static $validOps = [ + T_IS_IDENTICAL => true, + T_IS_NOT_IDENTICAL => true, + T_LESS_THAN => true, + T_GREATER_THAN => true, + T_IS_GREATER_OR_EQUAL => true, + T_IS_SMALLER_OR_EQUAL => true, + T_INSTANCEOF => true, + ]; + + /** + * A list of invalid operators with their alternatives. + * + * @var array + */ + private static $invalidOps = [ + 'PHP' => [ + T_IS_EQUAL => '===', + T_IS_NOT_EQUAL => '!==', + T_BOOLEAN_NOT => '=== FALSE', + ], + 'JS' => [ + T_IS_EQUAL => '===', + T_IS_NOT_EQUAL => '!==', + ], + ]; + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + T_INLINE_THEN, + T_WHILE, + T_FOR, + ]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where the token + * was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenizer = $phpcsFile->tokenizerType; + + if ($tokens[$stackPtr]['code'] === T_INLINE_THEN) { + $end = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$end]['code'] !== T_CLOSE_PARENTHESIS) { + // This inline IF statement does not have its condition + // bracketed, so we need to guess where it starts. + for ($i = ($end - 1); $i >= 0; $i--) { + if ($tokens[$i]['code'] === T_SEMICOLON) { + // Stop here as we assume it is the end + // of the previous statement. + break; + } else if ($tokens[$i]['code'] === T_OPEN_TAG) { + // Stop here as this is the start of the file. + break; + } else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET) { + // Stop if this is the closing brace of + // a code block. + if (isset($tokens[$i]['scope_opener']) === true) { + break; + } + } else if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + // Stop if this is the opening brace of + // a code block. + if (isset($tokens[$i]['scope_closer']) === true) { + break; + } + } else if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + // Stop if this is the start of a pair of + // parentheses that surrounds the inline + // IF statement. + if (isset($tokens[$i]['parenthesis_closer']) === true + && $tokens[$i]['parenthesis_closer'] >= $stackPtr + ) { + break; + } + }//end if + }//end for + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + } else { + if (isset($tokens[$end]['parenthesis_opener']) === false) { + return; + } + + $start = $tokens[$end]['parenthesis_opener']; + }//end if + } else if ($tokens[$stackPtr]['code'] === T_FOR) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $openingBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closingBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $start = $phpcsFile->findNext(T_SEMICOLON, $openingBracket, $closingBracket); + $end = $phpcsFile->findNext(T_SEMICOLON, ($start + 1), $closingBracket); + if ($start === false || $end === false) { + return; + } + } else { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $start = $tokens[$stackPtr]['parenthesis_opener']; + $end = $tokens[$stackPtr]['parenthesis_closer']; + }//end if + + $requiredOps = 0; + $foundOps = 0; + $foundBooleans = 0; + + $lastNonEmpty = $start; + + for ($i = $start; $i <= $end; $i++) { + $type = $tokens[$i]['code']; + if (isset(self::$invalidOps[$tokenizer][$type]) === true) { + $error = 'Operator %s prohibited; use %s instead'; + $data = [ + $tokens[$i]['content'], + self::$invalidOps[$tokenizer][$type], + ]; + $phpcsFile->addError($error, $i, 'NotAllowed', $data); + $foundOps++; + } else if (isset(self::$validOps[$type]) === true) { + $foundOps++; + } + + if ($type === T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) === true + && isset(Tokens::$functionNameTokens[$tokens[$lastNonEmpty]['code']]) === true + ) { + $i = $tokens[$i]['parenthesis_closer']; + $lastNonEmpty = $i; + continue; + } + + if ($tokens[$i]['code'] === T_TRUE || $tokens[$i]['code'] === T_FALSE) { + $foundBooleans++; + } + + if ($phpcsFile->tokenizerType !== 'JS' + && ($tokens[$i]['code'] === T_BOOLEAN_AND + || $tokens[$i]['code'] === T_BOOLEAN_OR) + ) { + $requiredOps++; + + // When the instanceof operator is used with another operator + // like ===, you can get more ops than are required. + if ($foundOps > $requiredOps) { + $foundOps = $requiredOps; + } + + // If we get to here and we have not found the right number of + // comparison operators, then we must have had an implicit + // true operation i.e., if ($a) instead of the required + // if ($a === true), so let's add an error. + if ($requiredOps !== $foundOps) { + $error = 'Implicit true comparisons prohibited; use === TRUE instead'; + $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue'); + $foundOps++; + } + } + + if (isset(Tokens::$emptyTokens[$type]) === false) { + $lastNonEmpty = $i; + } + }//end for + + $requiredOps++; + + if ($phpcsFile->tokenizerType !== 'JS' + && $foundOps < $requiredOps + && ($requiredOps !== $foundBooleans) + ) { + $error = 'Implicit true comparisons prohibited; use === TRUE instead'; + $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue'); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php new file mode 100644 index 000000000..cb3778453 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php @@ -0,0 +1,225 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IncrementDecrementUsageSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_INC, + T_DEC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_INC || $tokens[$stackPtr]['code'] === T_DEC) { + $this->processIncDec($phpcsFile, $stackPtr); + } else { + $this->processAssignment($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Checks to ensure increment and decrement operators are not confusing. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processIncDec($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Work out where the variable is so we know where to + // start looking for other operators. + if ($tokens[($stackPtr - 1)]['code'] === T_VARIABLE + || ($tokens[($stackPtr - 1)]['code'] === T_STRING + && ($tokens[($stackPtr - 2)]['code'] === T_OBJECT_OPERATOR + || $tokens[($stackPtr - 2)]['code'] === T_NULLSAFE_OBJECT_OPERATOR)) + ) { + $start = ($stackPtr + 1); + } else { + $start = ($stackPtr + 2); + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true); + if ($next === false) { + return; + } + + if (isset(Tokens::$arithmeticTokens[$tokens[$next]['code']]) === true) { + $error = 'Increment and decrement operators cannot be used in an arithmetic operation'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 3), null, true); + if ($prev === false) { + return; + } + + // Check if this is in a string concat. + if ($tokens[$next]['code'] === T_STRING_CONCAT || $tokens[$prev]['code'] === T_STRING_CONCAT) { + $error = 'Increment and decrement operators must be bracketed when used in string concatenation'; + $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); + } + + }//end processIncDec() + + + /** + * Checks to ensure increment and decrement operators are used. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processAssignment($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $assignedVar = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + // Not an assignment, return. + if ($tokens[$assignedVar]['code'] !== T_VARIABLE) { + return; + } + + $statementEnd = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SQUARE_BRACKET, T_CLOSE_CURLY_BRACKET], $stackPtr); + + // If there is anything other than variables, numbers, spaces or operators we need to return. + $noiseTokens = $phpcsFile->findNext([T_LNUMBER, T_VARIABLE, T_WHITESPACE, T_PLUS, T_MINUS, T_OPEN_PARENTHESIS], ($stackPtr + 1), $statementEnd, true); + + if ($noiseTokens !== false) { + return; + } + + // If we are already using += or -=, we need to ignore + // the statement if a variable is being used. + if ($tokens[$stackPtr]['code'] !== T_EQUAL) { + $nextVar = $phpcsFile->findNext(T_VARIABLE, ($stackPtr + 1), $statementEnd); + if ($nextVar !== false) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + $nextVar = ($stackPtr + 1); + $previousVariable = ($stackPtr + 1); + $variableCount = 0; + while (($nextVar = $phpcsFile->findNext(T_VARIABLE, ($nextVar + 1), $statementEnd)) !== false) { + $previousVariable = $nextVar; + $variableCount++; + } + + if ($variableCount !== 1) { + return; + } + + $nextVar = $previousVariable; + if ($tokens[$nextVar]['content'] !== $tokens[$assignedVar]['content']) { + return; + } + } + + // We have only one variable, and it's the same as what is being assigned, + // so we need to check what is being added or subtracted. + $nextNumber = ($stackPtr + 1); + $previousNumber = ($stackPtr + 1); + $numberCount = 0; + while (($nextNumber = $phpcsFile->findNext([T_LNUMBER], ($nextNumber + 1), $statementEnd, false)) !== false) { + $previousNumber = $nextNumber; + $numberCount++; + } + + if ($numberCount !== 1) { + return; + } + + $nextNumber = $previousNumber; + if ($tokens[$nextNumber]['content'] === '1') { + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + $opToken = $phpcsFile->findNext([T_PLUS, T_MINUS], ($nextVar + 1), $statementEnd); + if ($opToken === false) { + // Operator was before the variable, like: + // $var = 1 + $var; + // So we ignore it. + return; + } + + $operator = $tokens[$opToken]['content']; + } else { + $operator = substr($tokens[$stackPtr]['content'], 0, 1); + } + + // If we are adding or subtracting negative value, the operator + // needs to be reversed. + if ($tokens[$stackPtr]['code'] !== T_EQUAL) { + $negative = $phpcsFile->findPrevious(T_MINUS, ($nextNumber - 1), $stackPtr); + if ($negative !== false) { + if ($operator === '+') { + $operator = '-'; + } else { + $operator = '+'; + } + } + } + + $expected = $operator.$operator.$tokens[$assignedVar]['content']; + $found = $phpcsFile->getTokensAsString($assignedVar, ($statementEnd - $assignedVar + 1)); + + if ($operator === '+') { + $error = 'Increment'; + } else { + $error = 'Decrement'; + } + + $error .= " operators should be used where possible; found \"$found\" but expected \"$expected\""; + $phpcsFile->addError($error, $stackPtr, 'Found'); + }//end if + + }//end processAssignment() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php new file mode 100644 index 000000000..f9ea62020 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidLogicalOperatorsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_LOGICAL_AND, + T_LOGICAL_OR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $replacements = [ + 'and' => '&&', + 'or' => '||', + ]; + + $operator = strtolower($tokens[$stackPtr]['content']); + if (isset($replacements[$operator]) === false) { + return; + } + + $error = 'Logical operator "%s" is prohibited; use "%s" instead'; + $data = [ + $operator, + $replacements[$operator], + ]; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php new file mode 100644 index 000000000..04d063387 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php @@ -0,0 +1,288 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CommentedOutCodeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'CSS', + ]; + + /** + * If a comment is more than $maxPercentage% code, a warning will be shown. + * + * @var integer + */ + public $maxPercentage = 35; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore comments at the end of code blocks. + if (substr($tokens[$stackPtr]['content'], 0, 6) === '//end ') { + return; + } + + $content = ''; + $lastLineSeen = $tokens[$stackPtr]['line']; + $commentStyle = 'line'; + if (strpos($tokens[$stackPtr]['content'], '/*') === 0) { + $commentStyle = 'block'; + } + + $lastCommentBlockToken = $stackPtr; + for ($i = $stackPtr; $i < $phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + break; + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + continue; + } + + if (isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true) { + $lastLineSeen = $tokens[$i]['line']; + continue; + } + + if ($commentStyle === 'line' + && ($lastLineSeen + 1) <= $tokens[$i]['line'] + && strpos($tokens[$i]['content'], '/*') === 0 + ) { + // First non-whitespace token on a new line is start of a different style comment. + break; + } + + if ($commentStyle === 'line' + && ($lastLineSeen + 1) < $tokens[$i]['line'] + ) { + // Blank line breaks a '//' style comment block. + break; + } + + /* + Trim as much off the comment as possible so we don't + have additional whitespace tokens or comment tokens + */ + + $tokenContent = trim($tokens[$i]['content']); + $break = false; + + if ($commentStyle === 'line') { + if (substr($tokenContent, 0, 2) === '//') { + $tokenContent = substr($tokenContent, 2); + } + + if (substr($tokenContent, 0, 1) === '#') { + $tokenContent = substr($tokenContent, 1); + } + } else { + if (substr($tokenContent, 0, 3) === '/**') { + $tokenContent = substr($tokenContent, 3); + } + + if (substr($tokenContent, 0, 2) === '/*') { + $tokenContent = substr($tokenContent, 2); + } + + if (substr($tokenContent, -2) === '*/') { + $tokenContent = substr($tokenContent, 0, -2); + $break = true; + } + + if (substr($tokenContent, 0, 1) === '*') { + $tokenContent = substr($tokenContent, 1); + } + }//end if + + $content .= $tokenContent.$phpcsFile->eolChar; + $lastLineSeen = $tokens[$i]['line']; + + $lastCommentBlockToken = $i; + + if ($break === true) { + // Closer of a block comment found. + break; + } + }//end for + + // Ignore typical warning suppression annotations from other tools. + if (preg_match('`^\s*@[A-Za-z()\._-]+\s*$`', $content) === 1) { + return ($lastCommentBlockToken + 1); + } + + // Quite a few comments use multiple dashes, equals signs etc + // to frame comments and licence headers. + $content = preg_replace('/[-=#*]{2,}/', '-', $content); + + // Random numbers sitting inside the content can throw parse errors + // for invalid literals in PHP7+, so strip those. + $content = preg_replace('/\d+/', '', $content); + + $content = trim($content); + + if ($content === '') { + return ($lastCommentBlockToken + 1); + } + + if ($phpcsFile->tokenizerType === 'PHP') { + $content = ''; + } + + // Because we are not really parsing code, the tokenizer can throw all sorts + // of errors that don't mean anything, so ignore them. + $oldErrors = ini_get('error_reporting'); + ini_set('error_reporting', 0); + try { + $tokenizerClass = get_class($phpcsFile->tokenizer); + $tokenizer = new $tokenizerClass($content, $phpcsFile->config, $phpcsFile->eolChar); + $stringTokens = $tokenizer->getTokens(); + } catch (TokenizerException $e) { + // We couldn't check the comment, so ignore it. + ini_set('error_reporting', $oldErrors); + return ($lastCommentBlockToken + 1); + } + + ini_set('error_reporting', $oldErrors); + + $numTokens = count($stringTokens); + + /* + We know what the first two and last two tokens should be + (because we put them there) so ignore this comment if those + tokens were not parsed correctly. It obviously means this is not + valid code. + */ + + // First token is always the opening tag. + if ($stringTokens[0]['code'] !== T_OPEN_TAG) { + return ($lastCommentBlockToken + 1); + } else { + array_shift($stringTokens); + --$numTokens; + } + + // Last token is always the closing tag, unless something went wrong. + if (isset($stringTokens[($numTokens - 1)]) === false + || $stringTokens[($numTokens - 1)]['code'] !== T_CLOSE_TAG + ) { + return ($lastCommentBlockToken + 1); + } else { + array_pop($stringTokens); + --$numTokens; + } + + // Second last token is always whitespace or a comment, depending + // on the code inside the comment. + if ($phpcsFile->tokenizerType === 'PHP') { + if (isset(Tokens::$emptyTokens[$stringTokens[($numTokens - 1)]['code']]) === false) { + return ($lastCommentBlockToken + 1); + } + + if ($stringTokens[($numTokens - 1)]['code'] === T_WHITESPACE) { + array_pop($stringTokens); + --$numTokens; + } + } + + $emptyTokens = [ + T_WHITESPACE => true, + T_STRING => true, + T_STRING_CONCAT => true, + T_ENCAPSED_AND_WHITESPACE => true, + T_NONE => true, + T_COMMENT => true, + ]; + $emptyTokens += Tokens::$phpcsCommentTokens; + + $numComment = 0; + $numPossible = 0; + $numCode = 0; + $numNonWhitespace = 0; + + for ($i = 0; $i < $numTokens; $i++) { + if (isset($emptyTokens[$stringTokens[$i]['code']]) === true) { + // Looks like comment. + $numComment++; + } else if (isset(Tokens::$comparisonTokens[$stringTokens[$i]['code']]) === true + || isset(Tokens::$arithmeticTokens[$stringTokens[$i]['code']]) === true + || $stringTokens[$i]['code'] === T_GOTO_LABEL + ) { + // Commented out HTML/XML and other docs contain a lot of these + // characters, so it is best to not use them directly. + $numPossible++; + } else { + // Looks like code. + $numCode++; + } + + if ($stringTokens[$i]['code'] !== T_WHITESPACE) { + ++$numNonWhitespace; + } + } + + // Ignore comments with only two or less non-whitespace tokens. + // Sample size too small for a reliably determination. + if ($numNonWhitespace <= 2) { + return ($lastCommentBlockToken + 1); + } + + $percentCode = ceil((($numCode / $numTokens) * 100)); + if ($percentCode > $this->maxPercentage) { + // Just in case. + $percentCode = min(100, $percentCode); + + $error = 'This comment is %s%% valid code; is this commented out code?'; + $data = [$percentCode]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + + return ($lastCommentBlockToken + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php new file mode 100644 index 000000000..9d8077f59 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowBooleanStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) === true) { + // Any owner means we are not just a simple statement. + return; + } + } + } + + $error = 'Boolean operators are not allowed outside of control structure conditions'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php new file mode 100644 index 000000000..7c7e2246f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php @@ -0,0 +1,111 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowComparisonAssignmentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore default value assignments in function definitions. + $function = $phpcsFile->findPrevious(T_FUNCTION, ($stackPtr - 1), null, false, null, true); + if ($function !== false) { + $opener = $tokens[$function]['parenthesis_opener']; + $closer = $tokens[$function]['parenthesis_closer']; + if ($opener < $stackPtr && $closer > $stackPtr) { + return; + } + } + + // Ignore values in array definitions. + $array = $phpcsFile->findNext( + T_ARRAY, + ($stackPtr + 1), + null, + false, + null, + true + ); + + if ($array !== false) { + return; + } + + // Ignore function calls. + $ignore = [ + T_NULLSAFE_OBJECT_OPERATOR, + T_OBJECT_OPERATOR, + T_STRING, + T_VARIABLE, + T_WHITESPACE, + ]; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_CLOSURE + || ($tokens[$next]['code'] === T_OPEN_PARENTHESIS + && $tokens[($next - 1)]['code'] === T_STRING) + ) { + // Code will look like: $var = myFunction( + // and will be ignored. + return; + } + + $endStatement = $phpcsFile->findEndOfStatement($stackPtr); + for ($i = ($stackPtr + 1); $i < $endStatement; $i++) { + if ((isset(Tokens::$comparisonTokens[$tokens[$i]['code']]) === true + && $tokens[$i]['code'] !== T_COALESCE) + || $tokens[$i]['code'] === T_INLINE_THEN + ) { + $error = 'The value of a comparison must not be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'AssignedComparison'); + break; + } + + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_BOOLEAN_NOT + ) { + $error = 'The value of a boolean operation must not be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'AssignedBool'); + break; + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php new file mode 100644 index 000000000..60b0c370a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowInlineIfSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_THEN]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $phpcsFile->addError('Inline IF statements are not allowed', $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php new file mode 100644 index 000000000..4448d2445 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php @@ -0,0 +1,186 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowMultipleAssignmentsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore default value assignments in function definitions. + $function = $phpcsFile->findPrevious([T_FUNCTION, T_CLOSURE, T_FN], ($stackPtr - 1), null, false, null, true); + if ($function !== false) { + $opener = $tokens[$function]['parenthesis_opener']; + $closer = $tokens[$function]['parenthesis_closer']; + if ($opener < $stackPtr && $closer > $stackPtr) { + return; + } + } + + // Ignore assignments in WHILE loop conditions. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + foreach ($nested as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === true + && $tokens[$tokens[$opener]['parenthesis_owner']]['code'] === T_WHILE + ) { + return; + } + } + } + + // Ignore member var definitions. + if (empty($tokens[$stackPtr]['conditions']) === false) { + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if (isset(Tokens::$ooScopeTokens[$tokens[$deepestScope]['code']]) === true) { + return; + } + } + + /* + The general rule is: + Find an equal sign and go backwards along the line. If you hit an + end bracket, skip to the opening bracket. When you find a variable, + stop. That variable must be the first non-empty token on the line + or in the statement. If not, throw an error. + */ + + for ($varToken = ($stackPtr - 1); $varToken >= 0; $varToken--) { + if (in_array($tokens[$varToken]['code'], [T_SEMICOLON, T_OPEN_CURLY_BRACKET], true) === true) { + // We've reached the next statement, so we + // didn't find a variable. + return; + } + + // Skip brackets. + if (isset($tokens[$varToken]['parenthesis_opener']) === true && $tokens[$varToken]['parenthesis_opener'] < $varToken) { + $varToken = $tokens[$varToken]['parenthesis_opener']; + continue; + } + + if (isset($tokens[$varToken]['bracket_opener']) === true) { + $varToken = $tokens[$varToken]['bracket_opener']; + continue; + } + + if ($tokens[$varToken]['code'] === T_VARIABLE) { + // We found our variable. + break; + } + }//end for + + if ($varToken <= 0) { + // Didn't find a variable. + return; + } + + $start = $phpcsFile->findStartOfStatement($varToken); + + $allowed = Tokens::$emptyTokens; + + $allowed[T_STRING] = T_STRING; + $allowed[T_NS_SEPARATOR] = T_NS_SEPARATOR; + $allowed[T_DOUBLE_COLON] = T_DOUBLE_COLON; + $allowed[T_OBJECT_OPERATOR] = T_OBJECT_OPERATOR; + $allowed[T_ASPERAND] = T_ASPERAND; + $allowed[T_DOLLAR] = T_DOLLAR; + $allowed[T_SELF] = T_SELF; + $allowed[T_PARENT] = T_PARENT; + $allowed[T_STATIC] = T_STATIC; + + $varToken = $phpcsFile->findPrevious($allowed, ($varToken - 1), null, true); + + if ($varToken < $start + && $tokens[$varToken]['code'] !== T_OPEN_PARENTHESIS + && $tokens[$varToken]['code'] !== T_OPEN_SQUARE_BRACKET + ) { + $varToken = $start; + } + + // Ignore the first part of FOR loops as we are allowed to + // assign variables there even though the variable is not the + // first thing on the line. + if ($tokens[$varToken]['code'] === T_OPEN_PARENTHESIS && isset($tokens[$varToken]['parenthesis_owner']) === true) { + $owner = $tokens[$varToken]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FOR) { + return; + } + } + + if ($tokens[$varToken]['code'] === T_VARIABLE + || $tokens[$varToken]['code'] === T_OPEN_TAG + || $tokens[$varToken]['code'] === T_GOTO_LABEL + || $tokens[$varToken]['code'] === T_INLINE_THEN + || $tokens[$varToken]['code'] === T_INLINE_ELSE + || $tokens[$varToken]['code'] === T_SEMICOLON + || $tokens[$varToken]['code'] === T_CLOSE_PARENTHESIS + || isset($allowed[$tokens[$varToken]['code']]) === true + ) { + return; + } + + $error = 'Assignments must be the first block of code on a line'; + $errorCode = 'Found'; + + if (isset($nested) === true) { + $controlStructures = [ + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + T_SWITCH => T_SWITCH, + T_CASE => T_CASE, + T_FOR => T_FOR, + T_MATCH => T_MATCH, + ]; + foreach ($nested as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === true + && isset($controlStructures[$tokens[$tokens[$opener]['parenthesis_owner']]['code']]) === true + ) { + $errorCode .= 'InControlStructure'; + break; + } + } + } + + $phpcsFile->addError($error, $stackPtr, $errorCode); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php new file mode 100644 index 000000000..a0f1161c6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowSizeFunctionsInLoopsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * An array of functions we don't want in the condition of loops. + * + * @var array + */ + protected $forbiddenFunctions = [ + 'PHP' => [ + 'sizeof' => true, + 'strlen' => true, + 'count' => true, + ], + 'JS' => ['length' => true], + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_WHILE, + T_FOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenizer = $phpcsFile->tokenizerType; + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$stackPtr]['code'] === T_FOR) { + // We only want to check the condition in FOR loops. + $start = $phpcsFile->findNext(T_SEMICOLON, ($openBracket + 1)); + $end = $phpcsFile->findPrevious(T_SEMICOLON, ($closeBracket - 1)); + } else { + $start = $openBracket; + $end = $closeBracket; + } + + for ($i = ($start + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_STRING + && isset($this->forbiddenFunctions[$tokenizer][$tokens[$i]['content']]) === true + ) { + $functionName = $tokens[$i]['content']; + if ($tokenizer === 'JS') { + // Needs to be in the form object.function to be valid. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($prev === false || $tokens[$prev]['code'] !== T_OBJECT_OPERATOR) { + continue; + } + + $functionName = 'object.'.$functionName; + } else { + // Make sure it isn't a member var. + if ($tokens[($i - 1)]['code'] === T_OBJECT_OPERATOR + || $tokens[($i - 1)]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + continue; + } + + $functionName .= '()'; + } + + $error = 'The use of %s inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead'; + $data = [$functionName]; + $phpcsFile->addError($error, $i, 'Found', $data); + }//end if + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php new file mode 100644 index 000000000..9f86a1798 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php @@ -0,0 +1,38 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff as GenericForbiddenFunctionsSniff; + +class DiscouragedFunctionsSniff extends GenericForbiddenFunctionsSniff +{ + + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array + */ + public $forbiddenFunctions = [ + 'error_log' => null, + 'print_r' => null, + 'var_dump' => null, + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = false; + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php new file mode 100644 index 000000000..ef11aa6c4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php @@ -0,0 +1,402 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmbeddedPhpSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If the close php tag is on the same line as the opening + // then we have an inline embedded PHP block. + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closeTag === false || $tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) { + $this->validateMultilineEmbeddedPhp($phpcsFile, $stackPtr); + } else { + $this->validateInlineEmbeddedPhp($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Validates embedded PHP that exists on multiple lines. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prevTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)); + if ($prevTag === false) { + // This is the first open tag. + return; + } + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $closingTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closingTag !== false) { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), $phpcsFile->numTokens, true); + if ($nextContent === false) { + // Final closing tag. It will be handled elsewhere. + return; + } + + // We have an opening and a closing tag, that lie within other content. + if ($firstContent === $closingTag) { + $error = 'Empty embedded PHP tag found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i <= $closingTag; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + }//end if + + if ($tokens[$firstContent]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $padding = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $padding)); + $phpcsFile->fixer->endChangeset(); + } + } else { + // Check the indent of the first line, except if it is a scope closer. + if (isset($tokens[$firstContent]['scope_closer']) === false + || $tokens[$firstContent]['scope_closer'] !== $firstContent + ) { + // Check for a blank line at the top. + if ($tokens[$firstContent]['line'] > ($tokens[$stackPtr]['line'] + 1)) { + // Find a token on the blank line to throw the error on. + $i = $stackPtr; + do { + $i++; + } while ($tokens[$i]['line'] !== ($tokens[$stackPtr]['line'] + 1)); + + $error = 'Blank line found at start of embedded PHP content'; + $fix = $phpcsFile->addFixableError($error, $i, 'SpacingBefore'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $firstContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$firstContent]['line'] + || $tokens[$i]['line'] === $tokens[$stackPtr]['line'] + ) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr); + if ($first === false) { + $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + $indent = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else { + $indent = ($tokens[($first + 1)]['column'] - 1); + } + + $contentColumn = ($tokens[$firstContent]['column'] - 1); + if ($contentColumn !== $indent) { + $error = 'First line of embedded PHP code must be indented %s spaces; %s found'; + $data = [ + $indent, + $contentColumn, + ]; + $fix = $phpcsFile->addFixableError($error, $firstContent, 'Indent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $indent); + if ($contentColumn === 0) { + $phpcsFile->fixer->addContentBefore($firstContent, $padding); + } else { + $phpcsFile->fixer->replaceToken(($firstContent - 1), $padding); + } + } + } + }//end if + }//end if + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$lastContent]['line'] === $tokens[$stackPtr]['line'] + && trim($tokens[$lastContent]['content']) !== '' + ) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeOpen'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr); + if ($first === false) { + $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + $padding = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else { + $padding = ($tokens[($first + 1)]['column'] - 1); + } + + $phpcsFile->fixer->addContentBefore($stackPtr, $phpcsFile->eolChar.str_repeat(' ', $padding)); + } + } else { + // Find the first token on the first non-empty line we find. + for ($first = ($stackPtr - 1); $first > 0; $first--) { + if ($tokens[$first]['line'] === $tokens[$stackPtr]['line']) { + continue; + } else if (trim($tokens[$first]['content']) !== '') { + $first = $phpcsFile->findFirstOnLine([], $first, true); + break; + } + } + + $expected = 0; + if ($tokens[$first]['code'] === T_INLINE_HTML + && trim($tokens[$first]['content']) !== '' + ) { + $expected = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else if ($tokens[$first]['code'] === T_WHITESPACE) { + $expected = ($tokens[($first + 1)]['column'] - 1); + } + + $expected += 4; + $found = ($tokens[$stackPtr]['column'] - 1); + if ($found > $expected) { + $error = 'Opening PHP tag indent incorrect; expected no more than %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OpenTagIndent', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), str_repeat(' ', $expected)); + } + } + }//end if + + if ($closingTag === false) { + return; + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closingTag - 1), ($stackPtr + 1), true); + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), null, true); + + if ($tokens[$lastContent]['line'] === $tokens[$closingTag]['line']) { + $error = 'Closing PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closingTag, 'ContentBeforeEnd'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closingTag, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($closingTag, str_repeat(' ', ($tokens[$first]['column'] - 1))); + $phpcsFile->fixer->addNewlineBefore($closingTag); + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$nextContent]['line'] === $tokens[$closingTag]['line']) { + $error = 'Closing PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closingTag, 'ContentAfterEnd'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closingTag, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($closingTag); + $phpcsFile->fixer->addContent($closingTag, str_repeat(' ', ($tokens[$first]['column'] - 1))); + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $next = $phpcsFile->findNext(T_OPEN_TAG, ($closingTag + 1)); + if ($next === false) { + return; + } + + // Check for a blank line at the bottom. + if ((isset($tokens[$lastContent]['scope_closer']) === false + || $tokens[$lastContent]['scope_closer'] !== $lastContent) + && $tokens[$lastContent]['line'] < ($tokens[$closingTag]['line'] - 1) + ) { + // Find a token on the blank line to throw the error on. + $i = $closingTag; + do { + $i--; + } while ($tokens[$i]['line'] !== ($tokens[$closingTag]['line'] - 1)); + + $error = 'Blank line found at end of embedded PHP content'; + $fix = $phpcsFile->addFixableError($error, $i, 'SpacingAfter'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($lastContent + 1); $i < $closingTag; $i++) { + if ($tokens[$i]['line'] === $tokens[$lastContent]['line'] + || $tokens[$i]['line'] === $tokens[$closingTag]['line'] + ) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end validateMultilineEmbeddedPhp() + + + /** + * Validates embedded PHP that exists on one line. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + private function validateInlineEmbeddedPhp($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We only want one line PHP sections, so return if the closing tag is + // on the next line. + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr, null, false); + if ($tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) { + return; + } + + // Check that there is one, and only one space at the start of the statement. + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $closeTag, true); + + if ($firstContent === false) { + $error = 'Empty embedded PHP tag found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i <= $closeTag; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + // The open tag token always contains a single space after it. + $leadingSpace = 1; + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $leadingSpace = ($tokens[($stackPtr + 1)]['length'] + 1); + } + + if ($leadingSpace !== 1) { + $error = 'Expected 1 space after opening PHP tag; %s found'; + $data = [$leadingSpace]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterOpen', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closeTag - 1), $stackPtr, true); + if ($prev !== $stackPtr) { + if ((isset($tokens[$prev]['scope_opener']) === false + || $tokens[$prev]['scope_opener'] !== $prev) + && (isset($tokens[$prev]['scope_closer']) === false + || $tokens[$prev]['scope_closer'] !== $prev) + && $tokens[$prev]['code'] !== T_SEMICOLON + ) { + $error = 'Inline PHP statement must end with a semicolon'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSemicolon'); + if ($fix === true) { + $phpcsFile->fixer->addContent($prev, ';'); + } + } else if ($tokens[$prev]['code'] === T_SEMICOLON) { + $statementCount = 1; + for ($i = ($stackPtr + 1); $i < $prev; $i++) { + if ($tokens[$i]['code'] === T_SEMICOLON) { + $statementCount++; + } + } + + if ($statementCount > 1) { + $error = 'Inline PHP statement must contain a single statement; %s found'; + $data = [$statementCount]; + $phpcsFile->addError($error, $stackPtr, 'MultipleStatements', $data); + } + } + }//end if + + $trailingSpace = 0; + if ($tokens[($closeTag - 1)]['code'] === T_WHITESPACE) { + $trailingSpace = $tokens[($closeTag - 1)]['length']; + } else if (($tokens[($closeTag - 1)]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[($closeTag - 1)]['code']]) === true) + && substr($tokens[($closeTag - 1)]['content'], -1) === ' ' + ) { + $trailingSpace = (strlen($tokens[($closeTag - 1)]['content']) - strlen(rtrim($tokens[($closeTag - 1)]['content']))); + } + + if ($trailingSpace !== 1) { + $error = 'Expected 1 space before closing PHP tag; %s found'; + $data = [$trailingSpace]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeClose', $data); + if ($fix === true) { + if ($trailingSpace === 0) { + $phpcsFile->fixer->addContentBefore($closeTag, ' '); + } else if ($tokens[($closeTag - 1)]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[($closeTag - 1)]['code']]) === true + ) { + $phpcsFile->fixer->replaceToken(($closeTag - 1), rtrim($tokens[($closeTag - 1)]['content']).' '); + } else { + $phpcsFile->fixer->replaceToken(($closeTag - 1), ' '); + } + } + } + + }//end validateInlineEmbeddedPhp() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php new file mode 100644 index 000000000..3162c14b1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EvalSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EVAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of eval() is discouraged'; + $phpcsFile->addWarning($error, $stackPtr, 'Discouraged'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php new file mode 100644 index 000000000..024eff8ac --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class GlobalKeywordSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_GLOBAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextVar = $tokens[$phpcsFile->findNext([T_VARIABLE], $stackPtr)]; + $varName = str_replace('$', '', $nextVar['content']); + $error = 'Use of the "global" keyword is forbidden; use "$GLOBALS[\'%s\']" instead'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php new file mode 100644 index 000000000..67369cb22 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class HeredocSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_START_HEREDOC, + T_START_NOWDOC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of heredoc and nowdoc syntax ("<<<") is not allowed; use standard strings or inline HTML instead'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php new file mode 100644 index 000000000..4e3ee2152 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InnerFunctionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $function = $phpcsFile->getCondition($stackPtr, T_FUNCTION); + if ($function === false) { + // Not a nested function. + return; + } + + $class = $phpcsFile->getCondition($stackPtr, T_ANON_CLASS, false); + if ($class !== false && $class > $function) { + // Ignore methods in anon classes. + return; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_EQUAL) { + // Ignore closures. + return; + } + + $error = 'The use of inner functions is forbidden'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php new file mode 100644 index 000000000..519b7f6cc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercasePHPFunctionsSniff implements Sniff +{ + + /** + * String -> int hash map of all php built in function names + * + * @var array + */ + private $builtInFunctions; + + + /** + * Construct the LowercasePHPFunctionSniff + */ + public function __construct() + { + + $allFunctions = get_defined_functions(); + $this->builtInFunctions = array_flip($allFunctions['internal']); + + }//end __construct() + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content === $contentLc) { + return; + } + + // Make sure it is an inbuilt PHP function. + // PHP_CodeSniffer can possibly include user defined functions + // through the use of vendor/autoload.php. + if (isset($this->builtInFunctions[$contentLc]) === false) { + return; + } + + // Make sure this is a function call or a use statement. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false) { + // Not a function call. + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_BITWISE_AND; + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $prevPrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + + if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) { + // Is this a use statement importing a PHP native function ? + if ($tokens[$next]['code'] !== T_NS_SEPARATOR + && $tokens[$prev]['code'] === T_STRING + && $tokens[$prev]['content'] === 'function' + && $prevPrev !== false + && $tokens[$prevPrev]['code'] === T_USE + ) { + $error = 'Use statements for PHP native functions must be lowercase; expected "%s" but found "%s"'; + $data = [ + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseStatementUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + // No open parenthesis; not a "use function" statement nor a function call. + return; + }//end if + + if ($tokens[$prev]['code'] === T_FUNCTION) { + // Function declaration, not a function call. + return; + } + + if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { + if ($prevPrev !== false + && ($tokens[$prevPrev]['code'] === T_STRING + || $tokens[$prevPrev]['code'] === T_NAMESPACE + || $tokens[$prevPrev]['code'] === T_NEW) + ) { + // Namespaced class/function, not an inbuilt function. + // Could potentially give false negatives for non-namespaced files + // when namespace\functionName() is encountered. + return; + } + } + + if ($tokens[$prev]['code'] === T_NEW) { + // Object creation, not an inbuilt function. + return; + } + + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Not an inbuilt function. + return; + } + + if ($tokens[$prev]['code'] === T_DOUBLE_COLON) { + // Not an inbuilt function. + return; + } + + $error = 'Calls to PHP native functions must be lowercase; expected "%s" but found "%s"'; + $data = [ + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'CallUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php new file mode 100644 index 000000000..343d9b29e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php @@ -0,0 +1,277 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NonExecutableCodeSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_BREAK, + T_CONTINUE, + T_RETURN, + T_THROW, + T_EXIT, + T_GOTO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this token is preceded with an "or", it only relates to one line + // and should be ignored. For example: fopen() or die(). + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_LOGICAL_OR || $tokens[$prev]['code'] === T_BOOLEAN_OR) { + return; + } + + // Check if this token is actually part of a one-line IF or ELSE statement. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_opener']; + continue; + } else if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + break; + } + + if ($tokens[$i]['code'] === T_IF + || $tokens[$i]['code'] === T_ELSE + || $tokens[$i]['code'] === T_ELSEIF + ) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_RETURN) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + // If this is the closing brace of a function + // then this return statement doesn't return anything + // and is not required anyway. + $owner = $tokens[$next]['scope_condition']; + if ($tokens[$owner]['code'] === T_FUNCTION) { + $warning = 'Empty return statement not required here'; + $phpcsFile->addWarning($warning, $stackPtr, 'ReturnNotRequired'); + return; + } + } + } + } + + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $owner = $tokens[$stackPtr]['scope_condition']; + if ($tokens[$owner]['code'] === T_CASE || $tokens[$owner]['code'] === T_DEFAULT) { + // This token closes the scope of a CASE or DEFAULT statement + // so any code between this statement and the next CASE, DEFAULT or + // end of SWITCH token will not be executable. + $end = $phpcsFile->findEndOfStatement($stackPtr); + $next = $phpcsFile->findNext( + [ + T_CASE, + T_DEFAULT, + T_CLOSE_CURLY_BRACKET, + T_ENDSWITCH, + ], + ($end + 1) + ); + + if ($next !== false) { + $lastLine = $tokens[$end]['line']; + for ($i = ($stackPtr + 1); $i < $next; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $line = $tokens[$i]['line']; + if ($line > $lastLine) { + $type = substr($tokens[$stackPtr]['type'], 2); + $warning = 'Code after the %s statement on line %s cannot be executed'; + $data = [ + $type, + $tokens[$stackPtr]['line'], + ]; + $phpcsFile->addWarning($warning, $i, 'Unreachable', $data); + $lastLine = $line; + } + } + }//end if + + // That's all we have to check for these types of statements. + return; + }//end if + }//end if + + // This token may be part of an inline condition. + // If we find a closing parenthesis that belongs to a condition + // we should ignore this token. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($tokens[$prev]['parenthesis_owner']) === true) { + $owner = $tokens[$prev]['parenthesis_owner']; + $ignore = [ + T_IF => true, + T_ELSE => true, + T_ELSEIF => true, + ]; + if (isset($ignore[$tokens[$owner]['code']]) === true) { + return; + } + } + + $ourConditions = array_keys($tokens[$stackPtr]['conditions']); + + if (empty($ourConditions) === false) { + $condition = array_pop($ourConditions); + + if (isset($tokens[$condition]['scope_closer']) === false) { + return; + } + + // Special case for BREAK statements sitting directly inside SWITCH + // statements. If we get to this point, we know the BREAK is not being + // used to close a CASE statement, so it is most likely non-executable + // code itself (as is the case when you put return; break; at the end of + // a case). So we need to ignore this token. + if ($tokens[$condition]['code'] === T_SWITCH + && $tokens[$stackPtr]['code'] === T_BREAK + ) { + return; + } + + $closer = $tokens[$condition]['scope_closer']; + + // If the closer for our condition is shared with other openers, + // we will need to throw errors from this token to the next + // shared opener (if there is one), not to the scope closer. + $nextOpener = null; + for ($i = ($stackPtr + 1); $i < $closer; $i++) { + if (isset($tokens[$i]['scope_closer']) === true) { + if ($tokens[$i]['scope_closer'] === $closer) { + // We found an opener that shares the same + // closing token as us. + $nextOpener = $i; + break; + } + } + }//end for + + if ($nextOpener === null) { + $end = $closer; + } else { + $end = ($nextOpener - 1); + } + } else { + // This token is in the global scope. + if ($tokens[$stackPtr]['code'] === T_BREAK) { + return; + } + + // Throw an error for all lines until the end of the file. + $end = ($phpcsFile->numTokens - 1); + }//end if + + // Find the semicolon that ends this statement, skipping + // nested statements like FOR loops and closures. + for ($start = ($stackPtr + 1); $start < $phpcsFile->numTokens; $start++) { + if ($start === $end) { + break; + } + + if (isset($tokens[$start]['parenthesis_closer']) === true + && $tokens[$start]['code'] === T_OPEN_PARENTHESIS + ) { + $start = $tokens[$start]['parenthesis_closer']; + continue; + } + + if (isset($tokens[$start]['bracket_closer']) === true + && $tokens[$start]['code'] === T_OPEN_CURLY_BRACKET + ) { + $start = $tokens[$start]['bracket_closer']; + continue; + } + + if ($tokens[$start]['code'] === T_SEMICOLON) { + break; + } + }//end for + + if (isset($tokens[$start]) === false) { + return; + } + + $lastLine = $tokens[$start]['line']; + for ($i = ($start + 1); $i < $end; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true + || isset(Tokens::$bracketTokens[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_SEMICOLON + ) { + continue; + } + + // Skip whole functions and classes/interfaces because they are not + // technically executed code, but rather declarations that may be used. + if (isset(Tokens::$ooScopeTokens[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_FUNCTION + || $tokens[$i]['code'] === T_CLOSURE + ) { + if (isset($tokens[$i]['scope_closer']) === false) { + // Parse error/Live coding. + return; + } + + $i = $tokens[$i]['scope_closer']; + continue; + } + + $line = $tokens[$i]['line']; + if ($line > $lastLine) { + $type = substr($tokens[$stackPtr]['type'], 2); + $warning = 'Code after the %s statement on line %s cannot be executed'; + $data = [ + $type, + $tokens[$stackPtr]['line'], + ]; + $phpcsFile->addWarning($warning, $i, 'Unreachable', $data); + $lastLine = $line; + } + }//end for + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php new file mode 100644 index 000000000..5239b644e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; + +class MemberVarScopeSniff extends AbstractVariableSniff +{ + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $properties = $phpcsFile->getMemberProperties($stackPtr); + + if ($properties === [] || $properties['scope_specified'] !== false) { + return; + } + + $error = 'Scope modifier not specified for member variable "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php new file mode 100644 index 000000000..8a34a4f29 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MethodScopeSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $properties = $phpcsFile->getMethodProperties($stackPtr); + if ($properties['scope_specified'] === false) { + $error = 'Visibility must be declared on method "%s"'; + $data = [$methodName]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php new file mode 100644 index 000000000..79cb9f3f4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php @@ -0,0 +1,128 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class StaticThisUsageSniff extends AbstractScopeSniff +{ + + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() + { + parent::__construct([T_CLASS, T_TRAIT, T_ENUM, T_ANON_CLASS], [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + public function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + // Ignore abstract functions. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_STRING) { + // Not a function declaration, or incomplete. + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProps['is_static'] === false) { + return; + } + + $next = $stackPtr; + $end = $tokens[$stackPtr]['scope_closer']; + + $this->checkThisUsage($phpcsFile, $next, $end); + + }//end processTokenWithinScope() + + + /** + * Check for $this variable usage between $next and $end tokens. + * + * @param File $phpcsFile The current file being scanned. + * @param int $next The position of the next token to check. + * @param int $end The position of the last token to check. + * + * @return void + */ + private function checkThisUsage(File $phpcsFile, $next, $end) + { + $tokens = $phpcsFile->getTokens(); + + do { + $next = $phpcsFile->findNext([T_VARIABLE, T_ANON_CLASS], ($next + 1), $end); + if ($next === false) { + continue; + } + + if ($tokens[$next]['code'] === T_ANON_CLASS) { + $this->checkThisUsage($phpcsFile, $next, $tokens[$next]['scope_opener']); + $next = $tokens[$next]['scope_closer']; + continue; + } + + if ($tokens[$next]['content'] !== '$this') { + continue; + } + + $error = 'Usage of "$this" in static methods will cause runtime errors'; + $phpcsFile->addError($error, $next, 'Found'); + } while ($next !== false); + + }//end checkThisUsage() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php new file mode 100644 index 000000000..9d32e54a0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConcatenationSpacingSniff implements Sniff +{ + + /** + * The number of spaces before and after a string concat. + * + * @var integer + */ + public $spacing = 0; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING_CONCAT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[($stackPtr + 2)]) === false) { + // Syntax error or live coding, bow out. + return; + } + + $ignoreBefore = false; + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Spacing before must be preserved due to the here/nowdoc closing tag. + $ignoreBefore = true; + } + + $this->spacing = (int) $this->spacing; + + if ($ignoreBefore === false) { + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $before = 0; + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $before = 'newline'; + } else { + $before = $tokens[($stackPtr - 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before string concat', $before); + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $after = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $after = 'newline'; + } else { + $after = $tokens[($stackPtr + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after string concat', $after); + + if (($ignoreBefore === true + || $before === $this->spacing + || ($before === 'newline' + && $this->ignoreNewlines === true)) + && ($after === $this->spacing + || ($after === 'newline' + && $this->ignoreNewlines === true)) + ) { + return; + } + + if ($this->spacing === 0) { + $message = 'Concat operator must not be surrounded by spaces'; + $data = []; + } else { + if ($this->spacing > 1) { + $message = 'Concat operator must be surrounded by %s spaces'; + } else { + $message = 'Concat operator must be surrounded by a single space'; + } + + $data = [$this->spacing]; + } + + $fix = $phpcsFile->addFixableError($message, $stackPtr, 'PaddingFound', $data); + + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($ignoreBefore === false && ($before !== 'newline' || $this->ignoreNewlines === false)) { + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr - 1), $padding); + if ($this->spacing === 0 + && ($tokens[($stackPtr - 2)]['code'] === T_LNUMBER + || $tokens[($stackPtr - 2)]['code'] === T_DNUMBER) + ) { + $phpcsFile->fixer->replaceToken(($stackPtr - 2), '('.$tokens[($stackPtr - 2)]['content'].')'); + } + + $phpcsFile->fixer->endChangeset(); + } else if ($this->spacing > 0) { + $phpcsFile->fixer->addContent(($stackPtr - 1), $padding); + } + } + + if ($after !== 'newline' || $this->ignoreNewlines === false) { + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr + 1), $padding); + if ($this->spacing === 0 + && ($tokens[($stackPtr + 2)]['code'] === T_LNUMBER + || $tokens[($stackPtr + 2)]['code'] === T_DNUMBER) + ) { + $phpcsFile->fixer->replaceToken(($stackPtr + 2), '('.$tokens[($stackPtr + 2)]['content'].')'); + } + + $phpcsFile->fixer->endChangeset(); + } else if ($this->spacing > 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php new file mode 100644 index 000000000..1ff99b9ca --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php @@ -0,0 +1,144 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DoubleQuoteUsageSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If tabs are being converted to spaces by the tokeniser, the + // original content should be used instead of the converted content. + if (isset($tokens[$stackPtr]['orig_content']) === true) { + $workingString = $tokens[$stackPtr]['orig_content']; + } else { + $workingString = $tokens[$stackPtr]['content']; + } + + $lastStringToken = $stackPtr; + + $i = ($stackPtr + 1); + if (isset($tokens[$i]) === true) { + while ($i < $phpcsFile->numTokens + && $tokens[$i]['code'] === $tokens[$stackPtr]['code'] + ) { + if (isset($tokens[$i]['orig_content']) === true) { + $workingString .= $tokens[$i]['orig_content']; + } else { + $workingString .= $tokens[$i]['content']; + } + + $lastStringToken = $i; + $i++; + } + } + + $skipTo = ($lastStringToken + 1); + + // Check if it's a double quoted string. + if ($workingString[0] !== '"' || substr($workingString, -1) !== '"') { + return $skipTo; + } + + // The use of variables in double quoted strings is not allowed. + if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING) { + $stringTokens = token_get_all('addError($error, $stackPtr, 'ContainsVar', $data); + } + } + + return $skipTo; + }//end if + + $allowedChars = [ + '\0', + '\1', + '\2', + '\3', + '\4', + '\5', + '\6', + '\7', + '\n', + '\r', + '\f', + '\t', + '\v', + '\x', + '\b', + '\e', + '\u', + '\'', + ]; + + foreach ($allowedChars as $testChar) { + if (strpos($workingString, $testChar) !== false) { + return $skipTo; + } + } + + $error = 'String %s does not require double quotes; use single quotes instead'; + $data = [str_replace(["\r", "\n"], ['\r', '\n'], $workingString)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotRequired', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $innerContent = substr($workingString, 1, -1); + $innerContent = str_replace('\"', '"', $innerContent); + $innerContent = str_replace('\\$', '$', $innerContent); + $phpcsFile->fixer->replaceToken($stackPtr, "'$innerContent'"); + while ($lastStringToken !== $stackPtr) { + $phpcsFile->fixer->replaceToken($lastStringToken, ''); + $lastStringToken--; + } + + $phpcsFile->fixer->endChangeset(); + } + + return $skipTo; + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php new file mode 100644 index 000000000..512d878a4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EchoedStringsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ECHO]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. + if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_TAG], $stackPtr, null, false); + + // If the token before the semi-colon is not a closing parenthesis, then we are not concerned. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true); + if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + // If the parenthesis don't match, then we are not concerned. + if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes'); + + if (($phpcsFile->findNext(Tokens::$operators, $stackPtr, $end, false)) === false) { + // There are no arithmetic operators in this. + $error = 'Echoed strings should not be bracketed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($firstContent, ''); + if ($tokens[($firstContent - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent(($firstContent - 1), ' '); + } + + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php new file mode 100644 index 000000000..95f95ed6b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CastSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $expected = str_replace(' ', '', $content); + $expected = str_replace("\t", '', $expected); + + if ($content !== $expected) { + $error = 'Cast statements must not contain whitespace; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContainsWhiteSpace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..808888f40 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -0,0 +1,359 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_DO, + T_ELSE, + T_ELSEIF, + T_TRY, + T_CATCH, + T_FINALLY, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true + && isset($tokens[$stackPtr]['parenthesis_closer']) === true + ) { + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($parenOpener + 1)]['length']; + + if ($gap === 0) { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 'newline'); + $gap = 'newline'; + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $gap); + } + + $error = 'Expected 0 spaces after opening bracket; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), ''); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 0); + } + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line'] + && $tokens[($parenCloser - 1)]['code'] === T_WHITESPACE + ) { + $gap = $tokens[($parenCloser - 1)]['length']; + $error = 'Expected 0 spaces before closing bracket; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), ''); + } + + if ($gap === 0) { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 'newline'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $gap); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 0); + } + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + for ($firstContent = ($scopeOpener + 1); $firstContent < $phpcsFile->numTokens; $firstContent++) { + $code = $tokens[$firstContent]['code']; + + if ($code === T_WHITESPACE + || ($code === T_INLINE_HTML + && trim($tokens[$firstContent]['content']) === '') + ) { + continue; + } + + // Skip all empty tokens on the same line as the opener. + if ($tokens[$firstContent]['line'] === $tokens[$scopeOpener]['line'] + && (isset(Tokens::$emptyTokens[$code]) === true + || $code === T_CLOSE_TAG) + ) { + continue; + } + + break; + } + + // We ignore spacing for some structures that tend to have their own rules. + $ignore = [ + T_FUNCTION => true, + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_DOC_COMMENT_OPEN_TAG => true, + ]; + + if (isset($ignore[$tokens[$firstContent]['code']]) === false + && $tokens[$firstContent]['line'] >= ($tokens[$scopeOpener]['line'] + 2) + ) { + $gap = ($tokens[$firstContent]['line'] - $tokens[$scopeOpener]['line'] - 1); + $phpcsFile->recordMetric($stackPtr, 'Blank lines at start of control structure', $gap); + + $error = 'Blank line found at start of control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'SpacingAfterOpen'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($scopeOpener + 1); + while ($tokens[$i]['line'] !== $tokens[$firstContent]['line']) { + // Start removing content from the line after the opener. + if ($tokens[$i]['line'] !== $tokens[$scopeOpener]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $i++; + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Blank lines at start of control structure', 0); + }//end if + + if ($firstContent !== $scopeCloser) { + $lastContent = $phpcsFile->findPrevious( + T_WHITESPACE, + ($scopeCloser - 1), + null, + true + ); + + $lastNonEmptyContent = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($scopeCloser - 1), + null, + true + ); + + $checkToken = $lastContent; + if (isset($tokens[$lastNonEmptyContent]['scope_condition']) === true) { + $checkToken = $tokens[$lastNonEmptyContent]['scope_condition']; + } + + if (isset($ignore[$tokens[$checkToken]['code']]) === false + && $tokens[$lastContent]['line'] <= ($tokens[$scopeCloser]['line'] - 2) + ) { + $errorToken = $scopeCloser; + for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] < $tokens[$scopeCloser]['line']) { + $errorToken = $i; + break; + } + } + + $gap = ($tokens[$scopeCloser]['line'] - $tokens[$lastContent]['line'] - 1); + $phpcsFile->recordMetric($stackPtr, 'Blank lines at end of control structure', $gap); + + $error = 'Blank line found at end of control structure'; + $fix = $phpcsFile->addFixableError($error, $errorToken, 'SpacingBeforeClose'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] === $tokens[$scopeCloser]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$lastContent]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Blank lines at end of control structure', 0); + }//end if + }//end if + + if ($tokens[$stackPtr]['code'] === T_MATCH) { + // Move the scope closer to the semicolon/comma. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($scopeCloser + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['code'] === T_COMMA) + ) { + $scopeCloser = $next; + } + } + + $trailingContent = $phpcsFile->findNext( + T_WHITESPACE, + ($scopeCloser + 1), + null, + true + ); + + if ($tokens[$trailingContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$trailingContent]['code']]) === true + ) { + // Special exception for code where the comment about + // an ELSE or ELSEIF is written between the control structures. + $nextCode = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($scopeCloser + 1), + null, + true + ); + + if ($tokens[$nextCode]['code'] === T_ELSE + || $tokens[$nextCode]['code'] === T_ELSEIF + || $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + ) { + $trailingContent = $nextCode; + } + }//end if + + if ($tokens[$trailingContent]['code'] === T_ELSE) { + if ($tokens[$stackPtr]['code'] === T_IF) { + // IF with ELSE. + return; + } + } + + if ($tokens[$trailingContent]['code'] === T_WHILE + && $tokens[$stackPtr]['code'] === T_DO + ) { + // DO with WHILE. + return; + } + + if ($tokens[$trailingContent]['code'] === T_CLOSE_TAG) { + // At the end of the script or embedded code. + return; + } + + if (isset($tokens[$trailingContent]['scope_condition']) === true + && $tokens[$trailingContent]['scope_condition'] !== $trailingContent + && isset($tokens[$trailingContent]['scope_opener']) === true + && $tokens[$trailingContent]['scope_opener'] !== $trailingContent + ) { + // Another control structure's closing brace. + $owner = $tokens[$trailingContent]['scope_condition']; + if ($tokens[$owner]['code'] === T_FUNCTION) { + // The next content is the closing brace of a function + // so normal function rules apply and we can ignore it. + return; + } + + if ($tokens[$owner]['code'] === T_CLOSURE + && ($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true) + ) { + return; + } + + if ($tokens[$trailingContent]['line'] !== ($tokens[$scopeCloser]['line'] + 1)) { + $error = 'Blank line found after control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'LineAfterClose'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($scopeCloser + 1); + while ($tokens[$i]['line'] !== $tokens[$trailingContent]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + $i++; + } + + $phpcsFile->fixer->addNewline($scopeCloser); + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($tokens[$trailingContent]['code'] !== T_ELSE + && $tokens[$trailingContent]['code'] !== T_ELSEIF + && $tokens[$trailingContent]['code'] !== T_CATCH + && $tokens[$trailingContent]['code'] !== T_FINALLY + && $tokens[$trailingContent]['line'] === ($tokens[$scopeCloser]['line'] + 1) + ) { + $error = 'No blank line found after control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'NoLineAfterClose'); + if ($fix === true) { + $trailingContent = $phpcsFile->findNext( + T_WHITESPACE, + ($scopeCloser + 1), + null, + true + ); + + if (($tokens[$trailingContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$trailingContent]['code']]) === true) + && $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + ) { + $phpcsFile->fixer->addNewline($trailingContent); + } else { + $phpcsFile->fixer->addNewline($scopeCloser); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php new file mode 100644 index 000000000..68871990b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionClosingBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + + // Special case for empty JS functions. + if ($phpcsFile->tokenizerType === 'JS' && $prevContent === $tokens[$stackPtr]['scope_opener']) { + // In this case, the opening and closing brace must be + // right next to each other. + if ($tokens[$stackPtr]['scope_closer'] !== ($tokens[$stackPtr]['scope_opener'] + 1)) { + $error = 'The opening and closing braces of empty functions must be directly next to each other; e.g., function () {}'; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBetween'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $closeBrace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + return; + } + + $nestedFunction = false; + if ($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $nestedFunction = true; + } + + $braceLine = $tokens[$closeBrace]['line']; + $prevLine = $tokens[$prevContent]['line']; + $found = ($braceLine - $prevLine - 1); + + if ($nestedFunction === true) { + if ($found < 0) { + $error = 'Closing brace of nested function must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } else if ($found > 0) { + $error = 'Expected 0 blank lines before closing brace of nested function; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeNestedClose', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $changeMade = false; + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + // Try and maintain indentation. + if ($tokens[$i]['line'] === ($braceLine - 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + $changeMade = true; + } + + // Special case for when the last content contains the newline + // token as well, like with a comment. + if ($changeMade === false) { + $phpcsFile->fixer->replaceToken(($prevContent + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + } else { + if ($found !== 1) { + if ($found < 0) { + $found = 0; + } + + $error = 'Expected 1 blank line before closing function brace; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeClose', $data); + + if ($fix === true) { + if ($found > 1) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < ($closeBrace - 1); $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($i, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } else { + // Try and maintain indentation. + if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addNewlineBefore($closeBrace - 1); + } else { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php new file mode 100644 index 000000000..09c5a48a5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionOpeningBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + // Probably an interface or abstract method. + return; + } + + $openBrace = $tokens[$stackPtr]['scope_opener']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($openBrace + 1), null, true); + + if ($nextContent === $tokens[$stackPtr]['scope_closer']) { + // The next bit of content is the closing brace, so this + // is an empty function and should have a blank line + // between the opening and closing braces. + return; + } + + $braceLine = $tokens[$openBrace]['line']; + $nextLine = $tokens[$nextContent]['line']; + + $found = ($nextLine - $braceLine - 1); + if ($found > 0) { + $error = 'Expected 0 blank lines after opening function brace; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $openBrace, 'SpacingAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($openBrace + 1); $i < $nextContent; $i++) { + if ($tokens[$i]['line'] === $nextLine) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($openBrace); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php new file mode 100644 index 000000000..1f4704b91 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php @@ -0,0 +1,367 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionSpacingSniff implements Sniff +{ + + /** + * The number of blank lines between functions. + * + * @var integer + */ + public $spacing = 2; + + /** + * The number of blank lines before the first function in a class. + * + * @var integer + */ + public $spacingBeforeFirst = 2; + + /** + * The number of blank lines after the last function in a class. + * + * @var integer + */ + public $spacingAfterLast = 2; + + /** + * Original properties as set in a custom ruleset (if any). + * + * @var array|null + */ + private $rulesetProperties = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $previousNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($previousNonEmpty !== false + && $tokens[$previousNonEmpty]['code'] === T_OPEN_TAG + && $tokens[$previousNonEmpty]['line'] !== 1 + ) { + // Ignore functions at the start of an embedded PHP block. + return; + } + + // If the ruleset has only overridden the spacing property, use + // that value for all spacing rules. + if ($this->rulesetProperties === null) { + $this->rulesetProperties = []; + if (isset($phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']) === true + && isset($phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']['properties']) === true + ) { + $this->rulesetProperties = $phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']['properties']; + if (isset($this->rulesetProperties['spacing']) === true) { + if (isset($this->rulesetProperties['spacingBeforeFirst']) === false) { + $this->spacingBeforeFirst = $this->spacing; + } + + if (isset($this->rulesetProperties['spacingAfterLast']) === false) { + $this->spacingAfterLast = $this->spacing; + } + } + } + } + + $this->spacing = (int) $this->spacing; + $this->spacingBeforeFirst = (int) $this->spacingBeforeFirst; + $this->spacingAfterLast = (int) $this->spacingAfterLast; + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Must be an interface method, so the closer is the semicolon. + $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr); + } else { + $closer = $tokens[$stackPtr]['scope_closer']; + } + + $isFirst = false; + $isLast = false; + + $ignore = ([T_WHITESPACE => T_WHITESPACE] + Tokens::$methodPrefixes); + + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + + while ($tokens[$prev]['code'] === T_ATTRIBUTE_END) { + // Skip past function attributes. + $prev = $phpcsFile->findPrevious($ignore, ($tokens[$prev]['attribute_opener'] - 1), null, true); + } + + if ($tokens[$prev]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past function docblocks. + $prev = $phpcsFile->findPrevious($ignore, ($tokens[$prev]['comment_opener'] - 1), null, true); + } + + if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET) { + $isFirst = true; + } + + $next = $phpcsFile->findNext($ignore, ($closer + 1), null, true); + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$closer]['line'] + ) { + // Skip past "end" comments. + $next = $phpcsFile->findNext($ignore, ($next + 1), null, true); + } + + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + $isLast = true; + } + + /* + Check the number of blank lines + after the function. + */ + + // Allow for comments on the same line as the closer. + for ($nextLineToken = ($closer + 1); $nextLineToken < $phpcsFile->numTokens; $nextLineToken++) { + if ($tokens[$nextLineToken]['line'] !== $tokens[$closer]['line']) { + break; + } + } + + $requiredSpacing = $this->spacing; + $errorCode = 'After'; + if ($isLast === true) { + $requiredSpacing = $this->spacingAfterLast; + $errorCode = 'AfterLast'; + } + + $foundLines = 0; + if ($nextLineToken === ($phpcsFile->numTokens - 1)) { + // We are at the end of the file. + // Don't check spacing after the function because this + // should be done by an EOF sniff. + $foundLines = $requiredSpacing; + } else { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, $nextLineToken, null, true); + if ($nextContent === false) { + // We are at the end of the file. + // Don't check spacing after the function because this + // should be done by an EOF sniff. + $foundLines = $requiredSpacing; + } else { + $foundLines = ($tokens[$nextContent]['line'] - $tokens[$nextLineToken]['line']); + } + } + + if ($isLast === true) { + $phpcsFile->recordMetric($stackPtr, 'Function spacing after last', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Function spacing after', $foundLines); + } + + if ($foundLines !== $requiredSpacing) { + $error = 'Expected %s blank line'; + if ($requiredSpacing !== 1) { + $error .= 's'; + } + + $error .= ' after function; %s found'; + $data = [ + $requiredSpacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($error, $closer, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $nextLineToken; $i <= $nextContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + $phpcsFile->fixer->addContentBefore($i, str_repeat($phpcsFile->eolChar, $requiredSpacing)); + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + /* + Check the number of blank lines + before the function. + */ + + $prevLineToken = null; + for ($i = $stackPtr; $i >= 0; $i--) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } + + $prevLineToken = $i; + break; + } + + if ($prevLineToken === null) { + // Never found the previous line, which means + // there are 0 blank lines before the function. + $foundLines = 0; + $prevContent = 0; + $prevLineToken = 0; + } else { + $currentLine = $tokens[$stackPtr]['line']; + + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, $prevLineToken, null, true); + + if ($tokens[$prevContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$prevContent]['code']]) === true + ) { + // Ignore comments as they can have different spacing rules, and this + // isn't a proper function comment anyway. + return; + } + + while ($tokens[$prevContent]['code'] === T_ATTRIBUTE_END + && $tokens[$prevContent]['line'] === ($currentLine - 1) + ) { + // Account for function attributes. + $currentLine = $tokens[$tokens[$prevContent]['attribute_opener']]['line']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$prevContent]['attribute_opener'] - 1), null, true); + } + + if ($tokens[$prevContent]['code'] === T_DOC_COMMENT_CLOSE_TAG + && $tokens[$prevContent]['line'] === ($currentLine - 1) + ) { + // Account for function comments. + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$prevContent]['comment_opener'] - 1), null, true); + } + + $prevLineToken = $prevContent; + + // Before we throw an error, check that we are not throwing an error + // for another function. We don't want to error for no blank lines after + // the previous function and no blank lines before this one as well. + $prevLine = ($tokens[$prevContent]['line'] - 1); + $i = ($stackPtr - 1); + $foundLines = 0; + + $stopAt = 0; + if (isset($tokens[$stackPtr]['conditions']) === true) { + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_keys($conditions); + $stopAt = array_pop($conditions); + } + + while ($currentLine !== $prevLine && $currentLine > 1 && $i > $stopAt) { + if ($tokens[$i]['code'] === T_FUNCTION) { + // Found another interface or abstract function. + return; + } + + if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$tokens[$i]['scope_condition']]['code'] === T_FUNCTION + ) { + // Found a previous function. + return; + } + + $currentLine = $tokens[$i]['line']; + if ($currentLine === $prevLine) { + break; + } + + if ($tokens[($i - 1)]['line'] < $currentLine && $tokens[($i + 1)]['line'] > $currentLine) { + // This token is on a line by itself. If it is whitespace, the line is empty. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundLines++; + } + } + + $i--; + }//end while + }//end if + + $requiredSpacing = $this->spacing; + $errorCode = 'Before'; + if ($isFirst === true) { + $requiredSpacing = $this->spacingBeforeFirst; + $errorCode = 'BeforeFirst'; + + $phpcsFile->recordMetric($stackPtr, 'Function spacing before first', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Function spacing before', $foundLines); + } + + if ($foundLines !== $requiredSpacing) { + $error = 'Expected %s blank line'; + if ($requiredSpacing !== 1) { + $error .= 's'; + } + + $error .= ' before function; %s found'; + $data = [ + $requiredSpacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + $nextSpace = $phpcsFile->findNext(T_WHITESPACE, ($prevContent + 1), $stackPtr); + if ($nextSpace === false) { + $nextSpace = ($stackPtr - 1); + } + + if ($foundLines < $requiredSpacing) { + $padding = str_repeat($phpcsFile->eolChar, ($requiredSpacing - $foundLines)); + $phpcsFile->fixer->addContent($prevLineToken, $padding); + } else { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($nextSpace + 1), null, true); + $phpcsFile->fixer->beginChangeset(); + for ($i = $nextSpace; $i < $nextContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$prevContent]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + $phpcsFile->fixer->addContentBefore($i, str_repeat($phpcsFile->eolChar, $requiredSpacing)); + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php new file mode 100644 index 000000000..c1492bf7b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util; + +class LanguageConstructSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ECHO, + T_PRINT, + T_RETURN, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_NEW, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr + 1)]) === false) { + // Skip if there is no next token. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] === T_SEMICOLON) { + // No content for this language construct. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $content = $tokens[($stackPtr + 1)]['content']; + if ($content !== ' ') { + $error = 'Language constructs must be followed by a single space; expected 1 space but found "%s"'; + $data = [Util\Common::prepareForOutput($content)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'IncorrectSingle', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } else if ($tokens[($stackPtr + 1)]['code'] !== T_OPEN_PARENTHESIS) { + $error = 'Language constructs must be followed by a single space; expected "%s" but found "%s"'; + $data = [ + $tokens[$stackPtr]['content'].' '.$tokens[($stackPtr + 1)]['content'], + $tokens[$stackPtr]['content'].$tokens[($stackPtr + 1)]['content'], + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php new file mode 100644 index 000000000..a89a02a94 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php @@ -0,0 +1,102 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LogicalOperatorSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check there is one space before the operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before logical operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } else { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$prev]['line'] + && $tokens[($stackPtr - 1)]['length'] !== 1 + ) { + $found = $tokens[($stackPtr - 1)]['length']; + $error = 'Expected 1 space before logical operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpaceBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } + + // Check there is one space after the operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after logical operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$next]['line'] + && $tokens[($stackPtr + 1)]['length'] !== 1 + ) { + $found = $tokens[($stackPtr + 1)]['length']; + $error = 'Expected 1 space after logical operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpaceAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php new file mode 100644 index 000000000..0ece1acad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php @@ -0,0 +1,254 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MemberVarSpacingSniff extends AbstractVariableSniff +{ + + /** + * The number of blank lines between member vars. + * + * @var integer + */ + public $spacing = 1; + + /** + * The number of blank lines before the first member var. + * + * @var integer + */ + public $spacingBeforeFirst = 1; + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $validPrefixes = Tokens::$methodPrefixes; + $validPrefixes[] = T_VAR; + + $startOfStatement = $phpcsFile->findPrevious($validPrefixes, ($stackPtr - 1), null, false, null, true); + if ($startOfStatement === false) { + return; + } + + $endOfStatement = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1), null, false, null, true); + + $ignore = $validPrefixes; + $ignore[T_WHITESPACE] = T_WHITESPACE; + + $start = $startOfStatement; + for ($prev = ($startOfStatement - 1); $prev >= 0; $prev--) { + if (isset($ignore[$tokens[$prev]['code']]) === true) { + continue; + } + + if ($tokens[$prev]['code'] === T_ATTRIBUTE_END + && isset($tokens[$prev]['attribute_opener']) === true + ) { + $prev = $tokens[$prev]['attribute_opener']; + $start = $prev; + continue; + } + + break; + } + + if (isset(Tokens::$commentTokens[$tokens[$prev]['code']]) === true) { + // Assume the comment belongs to the member var if it is on a line by itself. + $prevContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($tokens[$prevContent]['line'] !== $tokens[$prev]['line']) { + // Check the spacing, but then skip it. + $foundLines = ($tokens[$startOfStatement]['line'] - $tokens[$prev]['line'] - 1); + if ($foundLines > 0) { + for ($i = ($prev + 1); $i < $startOfStatement; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'Expected 0 blank lines after member var comment; %s found'; + $data = [$foundLines]; + $fix = $phpcsFile->addFixableError($error, $prev, 'AfterComment', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + // Inline comments have the newline included in the content but + // docblocks do not. + if ($tokens[$prev]['code'] === T_COMMENT) { + $phpcsFile->fixer->replaceToken($prev, rtrim($tokens[$prev]['content'])); + } + + for ($i = ($prev + 1); $i <= $startOfStatement; $i++) { + if ($tokens[$i]['line'] === $tokens[$startOfStatement]['line']) { + break; + } + + // Remove the newline after the docblock, and any entirely + // empty lines before the member var. + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] === $tokens[$prev]['line'] + || ($tokens[$i]['column'] === 1 + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line']) + ) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + }//end if + + break; + }//end if + }//end for + }//end if + + $start = $prev; + }//end if + }//end if + + // There needs to be n blank lines before the var, not counting comments. + if ($start === $startOfStatement) { + // No comment found. + $first = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $start, true); + if ($first === false) { + $first = $start; + } + } else if ($tokens[$start]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + $first = $tokens[$start]['comment_opener']; + } else { + $first = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 1), null, true); + $first = $phpcsFile->findNext(array_merge(Tokens::$commentTokens, [T_ATTRIBUTE]), ($first + 1)); + } + + // Determine if this is the first member var. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($first - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$prev]['scope_condition']) === true + && $tokens[$tokens[$prev]['scope_condition']]['code'] === T_FUNCTION + ) { + return; + } + + if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET + && isset(Tokens::$ooScopeTokens[$tokens[$tokens[$prev]['scope_condition']]['code']]) === true + ) { + $errorMsg = 'Expected %s blank line(s) before first member var; %s found'; + $errorCode = 'FirstIncorrect'; + $spacing = (int) $this->spacingBeforeFirst; + } else { + $errorMsg = 'Expected %s blank line(s) before member var; %s found'; + $errorCode = 'Incorrect'; + $spacing = (int) $this->spacing; + } + + $foundLines = ($tokens[$first]['line'] - $tokens[$prev]['line'] - 1); + + if ($errorCode === 'FirstIncorrect') { + $phpcsFile->recordMetric($stackPtr, 'Member var spacing before first', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Member var spacing before', $foundLines); + } + + if ($foundLines === $spacing) { + if ($endOfStatement !== false) { + return $endOfStatement; + } + + return; + } + + $data = [ + $spacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($errorMsg, $startOfStatement, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $first; $i++) { + if ($tokens[$i]['line'] === $tokens[$prev]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$first]['line']) { + for ($x = 1; $x <= $spacing; $x++) { + $phpcsFile->fixer->addNewlineBefore($i); + } + + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + if ($endOfStatement !== false) { + return $endOfStatement; + } + + return; + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php new file mode 100644 index 000000000..cc5db1644 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php @@ -0,0 +1,167 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ObjectOperatorSpacingSniff implements Sniff +{ + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_NULLSAFE_OBJECT_OPERATOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $before = 0; + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $before = 'newline'; + } else { + $before = $tokens[($stackPtr - 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before object operator', $before); + $this->checkSpacingBeforeOperator($phpcsFile, $stackPtr, $before); + + if (isset($tokens[($stackPtr + 1)]) === false + || isset($tokens[($stackPtr + 2)]) === false + ) { + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $after = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $after = 'newline'; + } else { + $after = $tokens[($stackPtr + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after object operator', $after); + $this->checkSpacingAfterOperator($phpcsFile, $stackPtr, $after); + + }//end process() + + + /** + * Check the spacing before the operator. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param mixed $before The number of spaces found before the + * operator or the string 'newline'. + * + * @return boolean true if there was no error, false otherwise. + */ + protected function checkSpacingBeforeOperator(File $phpcsFile, $stackPtr, $before) + { + if ($before !== 0 + && ($before !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Space found before object operator'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $curPos = ($stackPtr - 1); + + $phpcsFile->fixer->beginChangeset(); + while ($tokens[$curPos]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($curPos, ''); + --$curPos; + } + + $phpcsFile->fixer->endChangeset(); + } + + return false; + } + + return true; + + }//end checkSpacingBeforeOperator() + + + /** + * Check the spacing after the operator. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param mixed $after The number of spaces found after the + * operator or the string 'newline'. + * + * @return boolean true if there was no error, false otherwise. + */ + protected function checkSpacingAfterOperator(File $phpcsFile, $stackPtr, $after) + { + if ($after !== 0 + && ($after !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Space found after object operator'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After'); + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $curPos = ($stackPtr + 1); + + $phpcsFile->fixer->beginChangeset(); + while ($tokens[$curPos]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($curPos, ''); + ++$curPos; + } + + $phpcsFile->fixer->endChangeset(); + } + + return false; + } + + return true; + + }//end checkSpacingAfterOperator() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php new file mode 100644 index 000000000..2627d10d9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -0,0 +1,381 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + /** + * Don't check spacing for assignment operators. + * + * This allows multiple assignment statements to be aligned. + * + * @var boolean + */ + public $ignoreSpacingBeforeAssignments = true; + + /** + * A list of tokens that aren't considered as operands. + * + * @var string[] + */ + private $nonOperandTokens = []; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + /* + First we setup an array of all the tokens that can come before + a T_MINUS or T_PLUS token to indicate that the token is not being + used as an operator. + */ + + // Trying to operate on a negative value; eg. ($var * -1). + $this->nonOperandTokens = Tokens::$operators; + + // Trying to compare a negative value; eg. ($var === -1). + $this->nonOperandTokens += Tokens::$comparisonTokens; + + // Trying to compare a negative value; eg. ($var || -1 === $b). + $this->nonOperandTokens += Tokens::$booleanOperators; + + // Trying to assign a negative value; eg. ($var = -1). + $this->nonOperandTokens += Tokens::$assignmentTokens; + + // Returning/printing a negative value; eg. (return -1). + $this->nonOperandTokens += [ + T_RETURN => T_RETURN, + T_ECHO => T_ECHO, + T_EXIT => T_EXIT, + T_PRINT => T_PRINT, + T_YIELD => T_YIELD, + T_FN_ARROW => T_FN_ARROW, + ]; + + // Trying to use a negative value; eg. myFunction($var, -2). + $this->nonOperandTokens += [ + T_CASE => T_CASE, + T_COLON => T_COLON, + T_COMMA => T_COMMA, + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_STRING_CONCAT => T_STRING_CONCAT, + ]; + + // Casting a negative value; eg. (array) -$a. + $this->nonOperandTokens += Tokens::$castTokens; + + /* + These are the tokens the sniff is looking for. + */ + + $targets = Tokens::$comparisonTokens; + $targets += Tokens::$operators; + $targets += Tokens::$assignmentTokens; + $targets[] = T_INLINE_THEN; + $targets[] = T_INLINE_ELSE; + $targets[] = T_INSTANCEOF; + + return $targets; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->isOperator($phpcsFile, $stackPtr) === false) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // Check there is one space before the & operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "&" operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAmp'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr - 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space before "&" operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAmp', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + }//end if + + $hasNext = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($hasNext === false) { + // Live coding/parse error at end of file. + return; + } + + // Check there is one space after the & operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "&" operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAmp'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space after "&" operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAmp', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + return; + }//end if + + $operator = $tokens[$stackPtr]['content']; + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE + && (($tokens[($stackPtr - 1)]['code'] === T_INLINE_THEN + && $tokens[($stackPtr)]['code'] === T_INLINE_ELSE) === false) + ) { + $error = "Expected 1 space before \"$operator\"; 0 found"; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); + } else if (isset(Tokens::$assignmentTokens[$tokens[$stackPtr]['code']]) === false + || $this->ignoreSpacingBeforeAssignments === false + ) { + // Throw an error for assignments only if enabled using the sniff property + // because other standards allow multiple spaces to align assignments. + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr - 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space before "%s"; %s found'; + $data = [ + $operator, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($found === 'newline') { + $i = ($stackPtr - 2); + while ($tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + $i--; + } + } + + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $hasNext = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($hasNext === false) { + // Live coding/parse error at end of file. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + // Skip short ternary such as: "$foo = $bar ?: true;". + if (($tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[($stackPtr + 1)]['code'] === T_INLINE_ELSE) + ) { + return; + } + + $error = "Expected 1 space after \"$operator\"; 0 found"; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); + } else { + if (isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line'] + ) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space after "%s"; %s found'; + $data = [ + $operator, + $found, + ]; + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonWhitespace !== false + && isset(Tokens::$commentTokens[$tokens[$nextNonWhitespace]['code']]) === true + && $found === 'newline' + ) { + // Don't auto-fix when it's a comment or PHPCS annotation on a new line as + // it causes fixer conflicts and can cause the meaning of annotations to change. + $phpcsFile->addError($error, $stackPtr, 'SpacingAfter', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + }//end if + + }//end process() + + + /** + * Checks if an operator is actually a different type of token in the current context. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the operator in + * the stack. + * + * @return boolean + */ + protected function isOperator(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip default values in function declarations. + // Skip declare statements. + if ($tokens[$stackPtr]['code'] === T_EQUAL + || $tokens[$stackPtr]['code'] === T_MINUS + ) { + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); + $bracket = array_pop($parenthesis); + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + $function = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$function]['code'] === T_FUNCTION + || $tokens[$function]['code'] === T_CLOSURE + || $tokens[$function]['code'] === T_FN + || $tokens[$function]['code'] === T_DECLARE + ) { + return false; + } + } + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + // Skip for '=&' case. + if (isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)]['code'] === T_BITWISE_AND + ) { + return false; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // If it's not a reference, then we expect one space either side of the + // bitwise operator. + if ($phpcsFile->isReference($stackPtr) === true) { + return false; + } + } + + if ($tokens[$stackPtr]['code'] === T_MINUS || $tokens[$stackPtr]['code'] === T_PLUS) { + // Check minus spacing, but make sure we aren't just assigning + // a minus value or returning one. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($this->nonOperandTokens[$tokens[$prev]['code']]) === true) { + return false; + } + }//end if + + return true; + + }//end isOperator() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php new file mode 100644 index 000000000..198460dfc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class PropertyLabelSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_PROPERTY, + T_LABEL, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $colon = $phpcsFile->findNext(T_COLON, ($stackPtr + 1)); + + if ($colon !== ($stackPtr + 1)) { + $error = 'There must be no space before the colon in a property/label declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + + if ($tokens[($colon + 1)]['code'] !== T_WHITESPACE || $tokens[($colon + 1)]['content'] !== ' ') { + $error = 'There must be a single space after the colon in a property/label declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After'); + if ($fix === true) { + if ($tokens[($colon + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($colon + 1), ' '); + } else { + $phpcsFile->fixer->addContent($colon, ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php new file mode 100644 index 000000000..fd0387534 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$scopeOpeners; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + // We need to actually find the first piece of content on this line, + // as if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $stackPtr, true); + while ($tokens[$lineStart]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($lineStart - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING + ) { + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], ($lineStart - 1), true); + } + + $startColumn = $tokens[$lineStart]['column']; + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + // Check that the closing brace is on it's own line. + $lastContent = $phpcsFile->findPrevious([T_INLINE_HTML, T_WHITESPACE, T_OPEN_TAG], ($scopeEnd - 1), $scopeStart, true); + for ($lineStart = $scopeEnd; $tokens[$lineStart]['column'] > 1; $lineStart--); + + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line'] + || ($tokens[$lineStart]['code'] === T_INLINE_HTML + && trim($tokens[$lineStart]['content']) !== '') + ) { + $error = 'Closing brace must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'ContentBefore'); + if ($fix === true) { + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) { + $phpcsFile->fixer->addNewlineBefore($scopeEnd); + } else { + $phpcsFile->fixer->addNewlineBefore(($lineStart + 1)); + } + } + + return; + } + + // Check now that the closing brace is lined up correctly. + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $scopeEnd, true); + $braceIndent = $tokens[$lineStart]['column']; + if ($tokens[$stackPtr]['code'] !== T_DEFAULT + && $tokens[$stackPtr]['code'] !== T_CASE + && $braceIndent !== $startColumn + ) { + $error = 'Closing brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + ($startColumn - 1), + ($braceIndent - 1), + ]; + + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data); + if ($fix === true) { + $diff = ($startColumn - $braceIndent); + if ($diff > 0) { + $phpcsFile->fixer->addContentBefore($lineStart, str_repeat(' ', $diff)); + } else { + $phpcsFile->fixer->substrToken(($lineStart - 1), 0, $diff); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php new file mode 100644 index 000000000..2d800f052 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php @@ -0,0 +1,169 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeKeywordSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $register = Tokens::$scopeModifiers; + $register[] = T_STATIC; + $register[] = T_READONLY; + return $register; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr + 1)]) === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$stackPtr]['code'] === T_STATIC) { + if (($nextToken === false || $tokens[$nextToken]['code'] === T_DOUBLE_COLON) + || $tokens[$prevToken]['code'] === T_NEW + ) { + // Late static binding, e.g., static:: OR new static() usage or live coding. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_TYPE_UNION + ) { + // Not a scope keyword, but a union return type. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_NULLABLE + ) { + // Not a scope keyword, but a return type. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_COLON + ) { + $prevPrevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true); + if ($prevPrevToken !== false + && $tokens[$prevPrevToken]['code'] === T_CLOSE_PARENTHESIS + ) { + // Not a scope keyword, but a return type. + return; + } + } + }//end if + + if ($tokens[$prevToken]['code'] === T_AS) { + // Trait visibility change, e.g., "use HelloWorld { sayHello as private; }". + return; + } + + $isInFunctionDeclaration = false; + if (empty($tokens[$stackPtr]['nested_parenthesis']) === false) { + // Check if this is PHP 8.0 constructor property promotion. + // In that case, we can't have multi-property definitions. + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + $lastCloseParens = end($nestedParens); + if (isset($tokens[$lastCloseParens]['parenthesis_owner']) === true + && $tokens[$tokens[$lastCloseParens]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $isInFunctionDeclaration = true; + } + } + + if ($nextToken !== false + && $tokens[$nextToken]['code'] === T_VARIABLE + && $isInFunctionDeclaration === false + ) { + $endOfStatement = $phpcsFile->findNext(T_SEMICOLON, ($nextToken + 1)); + if ($endOfStatement === false) { + // Live coding. + return; + } + + $multiProperty = $phpcsFile->findNext(T_VARIABLE, ($nextToken + 1), $endOfStatement); + if ($multiProperty !== false + && $tokens[$stackPtr]['line'] !== $tokens[$nextToken]['line'] + && $tokens[$nextToken]['line'] !== $tokens[$endOfStatement]['line'] + ) { + // Allow for multiple properties definitions to each be on their own line. + return; + } + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $spacing = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $spacing = 'newline'; + } else { + $spacing = $tokens[($stackPtr + 1)]['length']; + } + } + + if ($spacing !== 1) { + $error = 'Scope keyword "%s" must be followed by a single space; found %s'; + $data = [ + $tokens[$stackPtr]['content'], + $spacing, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + if ($spacing === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr + 2); $i < $phpcsFile->numTokens; $i++) { + if (isset($tokens[$i]) === false || $tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php new file mode 100644 index 000000000..bdcf9a5dd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SemicolonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SEMICOLON]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prevType = $tokens[($stackPtr - 1)]['code']; + if (isset(Tokens::$emptyTokens[$prevType]) === false) { + return; + } + + $nonSpace = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 2), null, true); + + // Detect whether this is a semi-colon for a condition in a `for()` control structure. + $forCondition = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + $closeParenthesis = end($nestedParens); + + if (isset($tokens[$closeParenthesis]['parenthesis_owner']) === true) { + $owner = $tokens[$closeParenthesis]['parenthesis_owner']; + + if ($tokens[$owner]['code'] === T_FOR) { + $forCondition = true; + $nonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 2), null, true); + } + } + } + + if ($tokens[$nonSpace]['code'] === T_SEMICOLON + || ($forCondition === true && $nonSpace === $tokens[$owner]['parenthesis_opener']) + || (isset($tokens[$nonSpace]['scope_opener']) === true + && $tokens[$nonSpace]['scope_opener'] === $nonSpace) + ) { + // Empty statement. + return; + } + + $expected = $tokens[$nonSpace]['content'].';'; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).';'; + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\r', $found); + $found = str_replace("\t", '\t', $found); + $error = 'Space found before semicolon; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($stackPtr - 1); + while (($tokens[$i]['code'] === T_WHITESPACE) && ($i > $nonSpace)) { + $phpcsFile->fixer->replaceToken($i, ''); + $i--; + } + + $phpcsFile->fixer->addContent($nonSpace, ';'); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php new file mode 100644 index 000000000..e99d829bc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php @@ -0,0 +1,265 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class SuperfluousWhitespaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + /** + * If TRUE, whitespace rules are not checked for blank lines. + * + * Blank lines are those that contain only whitespace. + * + * @var boolean + */ + public $ignoreBlankLines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + T_CLOSE_TAG, + T_WHITESPACE, + T_COMMENT, + T_DOC_COMMENT_WHITESPACE, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_OPEN_TAG) { + /* + Check for start of file whitespace. + */ + + if ($phpcsFile->tokenizerType !== 'PHP') { + // The first token is always the open tag inserted when tokenized + // and the second token is always the first piece of content in + // the file. If the second token is whitespace, there was + // whitespace at the start of the file. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + return; + } + + if ($phpcsFile->fixer->enabled === true) { + $stackPtr = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + } + } else { + // If it's the first token, then there is no space. + if ($stackPtr === 0) { + return; + } + + $beforeOpen = ''; + + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + // If we find something that isn't inline html then there is something previous in the file. + if ($tokens[$i]['type'] !== 'T_INLINE_HTML') { + return; + } + + $beforeOpen .= $tokens[$i]['content']; + } + + // If we have ended up with inline html make sure it isn't just whitespace. + if (preg_match('`^[\pZ\s]+$`u', $beforeOpen) !== 1) { + return; + } + }//end if + + $fix = $phpcsFile->addFixableError('Additional whitespace found at start of file', $stackPtr, 'StartFile'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = 0; $i < $stackPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) { + /* + Check for end of file whitespace. + */ + + if ($phpcsFile->tokenizerType === 'PHP') { + if (isset($tokens[($stackPtr + 1)]) === false) { + // The close PHP token is the last in the file. + return; + } + + $afterClose = ''; + + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + // If we find something that isn't inline HTML then there + // is more to the file. + if ($tokens[$i]['type'] !== 'T_INLINE_HTML') { + return; + } + + $afterClose .= $tokens[$i]['content']; + } + + // If we have ended up with inline html make sure it isn't just whitespace. + if (preg_match('`^[\pZ\s]+$`u', $afterClose) !== 1) { + return; + } + } else { + // The last token is always the close tag inserted when tokenized + // and the second last token is always the last piece of content in + // the file. If the second last token is whitespace, there was + // whitespace at the end of the file. + $stackPtr--; + + // The pointer is now looking at the last content in the file and + // not the fake PHP end tag the tokenizer inserted. + if ($tokens[$stackPtr]['code'] !== T_WHITESPACE) { + return; + } + + // Allow a single newline at the end of the last line in the file. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE + && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar + ) { + return; + } + }//end if + + $fix = $phpcsFile->addFixableError('Additional whitespace found at end of file', $stackPtr, 'EndFile'); + if ($fix === true) { + if ($phpcsFile->tokenizerType !== 'PHP') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $stackPtr = ($prev + 1); + } + + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + /* + Check for end of line whitespace. + */ + + // Ignore whitespace that is not at the end of a line. + if (isset($tokens[($stackPtr + 1)]['line']) === true + && $tokens[($stackPtr + 1)]['line'] === $tokens[$stackPtr]['line'] + ) { + return; + } + + // Ignore blank lines if required. + if ($this->ignoreBlankLines === true + && $tokens[$stackPtr]['code'] === T_WHITESPACE + && $tokens[($stackPtr - 1)]['line'] !== $tokens[$stackPtr]['line'] + ) { + return; + } + + $tokenContent = rtrim($tokens[$stackPtr]['content'], $phpcsFile->eolChar); + if (empty($tokenContent) === false) { + if ($tokenContent !== rtrim($tokenContent)) { + $fix = $phpcsFile->addFixableError('Whitespace found at end of line', $stackPtr, 'EndLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, rtrim($tokenContent).$phpcsFile->eolChar); + } + } + } else if ($tokens[($stackPtr - 1)]['content'] !== rtrim($tokens[($stackPtr - 1)]['content']) + && $tokens[($stackPtr - 1)]['line'] === $tokens[$stackPtr]['line'] + ) { + $fix = $phpcsFile->addFixableError('Whitespace found at end of line', ($stackPtr - 1), 'EndLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), rtrim($tokens[($stackPtr - 1)]['content'])); + } + } + + /* + Check for multiple blank lines in a function. + */ + + if (($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true) + && $tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] + && $tokens[($stackPtr - 2)]['line'] === $tokens[($stackPtr - 1)]['line'] + ) { + // Properties and functions in nested classes have their own rules for spacing. + $conditions = $tokens[$stackPtr]['conditions']; + $deepestScope = end($conditions); + if ($deepestScope === T_ANON_CLASS) { + return; + } + + // This is an empty line and the line before this one is not + // empty, so this could be the start of a multiple empty + // line block. + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr, null, true); + $lines = ($tokens[$next]['line'] - $tokens[$stackPtr]['line']); + if ($lines > 1) { + $error = 'Functions must not contain multiple empty lines in a row; found %s empty lines'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EmptyLines', [$lines]); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = $stackPtr; + while ($tokens[$i]['line'] !== $tokens[$next]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + $i++; + } + + $phpcsFile->fixer->addNewlineBefore($i); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc new file mode 100644 index 000000000..8ffc868a3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc @@ -0,0 +1,31 @@ + 'bar', + 'bar' => 'foo', +]; + +if ($foo) {} +[$a, $b] = $c; + +echo foo()[ 1 ]; + +echo $this->addedCustomFunctions['nonce']; +echo $this->deprecated_functions[ $function_name ]['version']; + +echo [ 1,2,3 ][0]; +echo [ 1,2,3 ][ 0 ]; +echo 'PHP'[ 0 ]; + +$array = []; +$var = $var[$var[$var]]]; // Syntax error +$var = $var[$var[$var]; // Syntax error + +$myArray[ /* key start */'key'] = $value; +$myArray[ /* key start */'key'/* key end */ ] = $value; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..41d664092 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed @@ -0,0 +1,31 @@ + 'bar', + 'bar' => 'foo', +]; + +if ($foo) {} +[$a, $b] = $c; + +echo foo()[1]; + +echo $this->addedCustomFunctions['nonce']; +echo $this->deprecated_functions[$function_name]['version']; + +echo [ 1,2,3 ][0]; +echo [ 1,2,3 ][0]; +echo 'PHP'[0]; + +$array = []; +$var = $var[$var[$var]]]; // Syntax error +$var = $var[$var[$var]; // Syntax error + +$myArray[/* key start */'key'] = $value; +$myArray[/* key start */'key'/* key end */] = $value; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php new file mode 100644 index 000000000..304a0d424 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Arrays; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ArrayBracketSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 3, + 7 => 3, + 17 => 2, + 20 => 2, + 23 => 2, + 24 => 2, + 30 => 1, + 31 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc new file mode 100644 index 000000000..2774660c0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc @@ -0,0 +1,488 @@ + 1, + ); +} + +class TestClass +{ + public $good = array( + 'width' => '', + 'height' => '', + ); + + private $_bad = Array( + 'width' => '', + 'height' => '' + ); + + + public function test() + { + $truck = array( + 'width' => '', + 'height' => '', + ); + + $plane = Array( + 'width' => '', + 'height' => '', + ); + + $car = array( + 'width' => '', + 'height' => '', + ); + + $bus = array( + 'width' => '', + 'height' => '' + ); + + $train = array ( + TRUE, + FALSE, + 'aaa' + ); + + $inline = array('aaa', 'bbb', 'ccc'); + $inline = array('aaa'); + $inline = Array('aaa'); + + $bigone = array( + 'name' => 'bigone', + 'children' => Array( + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => Array( + 'child' => 'aaa', + ), + ), + 'short_name' => 'big' + ); + } + +}//end class + +$value = array ( ); +$value = array( ); +$value = array('1'=>$one, '2' => $two, '3'=> $three, '4' =>$four); +$value = array('1'=>$one); + +if (in_array('1', array('1','2','3')) === TRUE) { + $value = in_array('1', array('1' , '2', '3','4')); +} + +$value = array( + '1'=> TRUE, + FALSE, + '3' => 'aaa',); + +$value = array( + '1'=> TRUE, + FALSE, + ); + +$value = array( + TRUE, + '1' => FALSE, + ); + +$value = array(1, + 2 , + 3 , + ); + +$value = array(1 => $one, + 2 => $two , + 3 => $three , + ); + +$value = array( + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2 + ) + ); + +// Space in second arg. +$args = array( + '"'.$this->id.'"', + (int) $hasSessions, + ); + +// No errors. +$paths = array( + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ); + +$x = array( + ); + +$x = array('test' + ); +$x = array('test', + ); +$x = array('name' => 'test', + ); + +$x = array( + $x, + ); + +$func = array( + $x, + 'get'.$x.'Replacement' + ); + +$array = array( + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ); + +$array = array( + 'input_one', + 'inputTwo', + 'input_3', + ); + +// Malformed +$foo = array(1 +, 2); + +$listItems[$aliasPath] = array('itemContent' => implode('
    ', $aliases)); + +$listItems[$aliasPath] = array( + 'itemContent' => implode('
    ', $aliases) + ); + +$x = array + ( + $x, + $y, + ); + +$x = array +( + $x, + $y, + ); + +$x = array( + + $x, + $y, + ); + +$test = array( + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ); + +$c = array('a' => 1,); + +function b() +{ + $a = array( + 'a' => a('a'), + + ); + +} + +$foo = Array('[',']',':',"\n","\r"); +$bar = Array('[',']',':',' ',' '); + +function foo() +{ + return array($a, $b->screen); +} + +$array = array( + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => array( + new \Zend\Validator\InArray(array('haystack' => array_keys($aSubjects))), + ), + ); + +$var = array( + 'ViewHelper', + array('Foo'), + 'Errors', + ); + +$data = array( + 'first', + 'second', + 'third', + // Add more here + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$data = array( + 'first', + 'second' + //'third', + ); + +$foo = array( + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ); + +$foo = array( + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ); + +$weightings = array( + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ); + +foreach (array( + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ) as $key => $value) { +} + +$ids = array( + '1', // Foo. + '13', // Bar. + ); + +array( + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + } +); + +array( + 'key1' => array( + '1', + '2', + ) +); + +$var = array( + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ); + +function test() : array +{ + return []; +} + +$fields = array( + 'id' => array('type' => 'INT'), + 'value' => array('type' => 'VARCHAR')); + +get_current_screen()->add_help_tab( array( + 'id' => << false); + +$x = array( + 'xxxx' => array('aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false), +); + +$foo = array + ('foo' => array + ('bar1' => 1 + ,'bar2' => 1 + ,'bar3' => 1 + ,'bar4' => 1 + ,'bar5' => 1 + ) + ); + +$foo = array( + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ); + +$foo = foo( + array( + // comment + ) +); + +$foo = array( + << lorem( + 1 + ), 2 => 2, +); + +$foo = array( + 'тип' => 'авто', + 'цвет' => 'синий', + ); + +$paths = array( + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ); + +$foo = array(<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ); + +$array = array( + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ); + +$foo = array( + $this->fn => 'value', + $foo->fn => 'value', + ); + +array($a, $b, +$c); + +array('a' => $a, 'b' => $b, +'c' => $c); + +array( + static function() { + return null; + }, + (array) array(), + (bool) array(), + (double) array(), + (int) array(), + (object) array(), + (string) array(), + (unset) array(), +); + +array( + 'foo', + 'bar' + // This is a non-fixable error. + , +); + +yield array( + static fn () : string => '', +); + +yield array( + static fn () : string => '', + ); + +$foo = [ + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ]; + +// Intentional syntax error. +$a = array( + 'a' => + ); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed new file mode 100644 index 000000000..b45200648 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,524 @@ + 1); +} + +class TestClass +{ + public $good = array( + 'width' => '', + 'height' => '', + ); + + private $_bad = array( + 'width' => '', + 'height' => '', + ); + + + public function test() + { + $truck = array( + 'width' => '', + 'height' => '', + ); + + $plane = array( + 'width' => '', + 'height' => '', + ); + + $car = array( + 'width' => '', + 'height' => '', + ); + + $bus = array( + 'width' => '', + 'height' => '', + ); + + $train = array( + TRUE, + FALSE, + 'aaa', + ); + + $inline = array( + 'aaa', + 'bbb', + 'ccc', + ); + $inline = array('aaa'); + $inline = array('aaa'); + + $bigone = array( + 'name' => 'bigone', + 'children' => array( + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => array('child' => 'aaa'), + ), + 'short_name' => 'big', + ); + } + +}//end class + +$value = array(); +$value = array(); +$value = array( + '1' => $one, + '2' => $two, + '3' => $three, + '4' => $four, + ); +$value = array('1' => $one); + +if (in_array('1', array('1', '2', '3')) === TRUE) { + $value = in_array('1', array('1', '2', '3', '4')); +} + +$value = array( + '1'=> TRUE, + FALSE, + '3' => 'aaa', + ); + +$value = array( + '1'=> TRUE, + FALSE, + ); + +$value = array( + TRUE, + '1' => FALSE, + ); + +$value = array( + 1, + 2, + 3, + ); + +$value = array( + 1 => $one, + 2 => $two, + 3 => $three, + ); + +$value = array( + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +// Space in second arg. +$args = array( + '"'.$this->id.'"', + (int) $hasSessions, + ); + +// No errors. +$paths = array( + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ); + +$x = array(); + +$x = array('test'); +$x = array('test'); +$x = array('name' => 'test'); + +$x = array($x); + +$func = array( + $x, + 'get'.$x.'Replacement', + ); + +$array = array( + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ); + +$array = array( + 'input_one', + 'inputTwo', + 'input_3', + ); + +// Malformed +$foo = array( + 1, + 2, + ); + +$listItems[$aliasPath] = array('itemContent' => implode('
    ', $aliases)); + +$listItems[$aliasPath] = array( + 'itemContent' => implode('
    ', $aliases), + ); + +$x = array( + $x, + $y, + ); + +$x = array( + $x, + $y, + ); + +$x = array( + + $x, + $y, + ); + +$test = array( + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ); + +$c = array('a' => 1); + +function b() +{ + $a = array( + 'a' => a('a'), + + ); + +} + +$foo = array( + '[', + ']', + ':', + "\n", + "\r", + ); +$bar = array( + '[', + ']', + ':', + ' ', + ' ', + ); + +function foo() +{ + return array( + $a, + $b->screen, + ); +} + +$array = array( + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => array( + new \Zend\Validator\InArray(array('haystack' => array_keys($aSubjects))), + ), + ); + +$var = array( + 'ViewHelper', + array('Foo'), + 'Errors', + ); + +$data = array( + 'first', + 'second', + 'third', + // Add more here + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$foo = array( + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ); + +$foo = array( + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ); + +$weightings = array( + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ); + +foreach (array( + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ) as $key => $value) { +} + +$ids = array( + '1', // Foo. + '13', // Bar. + ); + +array( + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + }, +); + +array( + 'key1' => array( + '1', + '2', + ), +); + +$var = array( + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ); + +function test() : array +{ + return []; +} + +$fields = array( + 'id' => array('type' => 'INT'), + 'value' => array('type' => 'VARCHAR'), + ); + +get_current_screen()->add_help_tab( array( + 'id' => << false); + +$x = array( + 'xxxx' => array( + 'aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false, + ), + ); + +$foo = array( + 'foo' => array( + 'bar1' => 1, + 'bar2' => 1, + 'bar3' => 1, + 'bar4' => 1, + 'bar5' => 1, + ), + ); + +$foo = array( + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ); + +$foo = foo( + array( + // comment + ) +); + +$foo = array( + << lorem( + 1 + ), + 2 => 2, +); + +$foo = array( + 'тип' => 'авто', + 'цвет' => 'синий', + ); + +$paths = array( + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ); + +$foo = array(<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ); + +$array = array( + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ); + +$foo = array( + $this->fn => 'value', + $foo->fn => 'value', + ); + +array( + $a, + $b, + $c, +); + +array( + 'a' => $a, + 'b' => $b, + 'c' => $c, +); + +array( + static function() { + return null; + }, + (array) array(), + (bool) array(), + (double) array(), + (int) array(), + (object) array(), + (string) array(), + (unset) array(), +); + +array( + 'foo', + 'bar' + // This is a non-fixable error. + , +); + +yield array( + static fn () : string => '', + ); + +yield array( + static fn () : string => '', + ); + +$foo = [ + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ]; + +// Intentional syntax error. +$a = array( + 'a' => + ); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc new file mode 100644 index 000000000..621970fa1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc @@ -0,0 +1,470 @@ + 1, + ]; +} + +class TestClass +{ + public $good = [ + 'width' => '', + 'height' => '', + ]; + + private $_bad = [ + 'width' => '', + 'height' => '' + ]; + + + public function test() + { + $truck = [ + 'width' => '', + 'height' => '', + ]; + + $plane = [ + 'width' => '', + 'height' => '', + ]; + + $car = [ + 'width' => '', + 'height' => '', + ]; + + $bus = [ + 'width' => '', + 'height' => '' + ]; + + $train = [ + TRUE, + FALSE, + 'aaa' + ]; + + $inline = ['aaa', 'bbb', 'ccc']; + $inline = ['aaa']; + $inline = ['aaa']; + + $bigone = [ + 'name' => 'bigone', + 'children' => [ + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => [ + 'child' => 'aaa', + ], + ], + 'short_name' => 'big' + ]; + } + +}//end class + +$value = [ ]; +$value = [ ]; +$value = ['1'=>$one, '2' => $two, '3'=> $three, '4' =>$four]; +$value = ['1'=>$one]; + +if (in_array('1', ['1','2','3']) === TRUE) { + $value = in_array('1', ['1' , '2', '3','4']); +} + +$value = [ + '1'=> TRUE, + FALSE, + '3' => 'aaa',]; + +$value = [ + '1'=> TRUE, + FALSE, + ]; + +$value = [ + TRUE, + '1' => FALSE, + ]; + +$value = [1, + 2 , + 3 , + ]; + +$value = [1 => $one, + 2 => $two , + 3 => $three , + ]; + +$value = [ + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2 + ] + ]; + +// Space in second arg. +$args = [ + '"'.$this->id.'"', + (int) $hasSessions, + ]; + +// No errors. +$paths = [ + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ]; + +$x = [ + ]; + +$x = ['test' + ]; +$x = ['test', + ]; +$x = ['name' => 'test', + ]; + +$x = [ + $x, + ]; + +$func = [ + $x, + 'get'.$x.'Replacement' + ]; + +$array = [ + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ]; + +$array = [ + 'input_one', + 'inputTwo', + 'input_3', + ]; + +// Malformed +$foo = [1 +, 2]; + +$listItems[$aliasPath] = ['itemContent' => implode('
    ', $aliases)]; + +$listItems[$aliasPath] = [ + 'itemContent' => implode('
    ', $aliases) + ]; + +$x = + [ + $x, + $y, + ]; + +$x = +[ + $x, + $y, + ]; + +$x = [ + + $x, + $y, + ]; + +$test = [ + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ]; + +$c = ['a' => 1,]; +$c->{$var}[ ] = 2; + +$foo = ['[',']',':',"\n","\r"]; +$bar = ['[',']',':',' ',' ']; + +function foo() +{ + return [$a, $b->screen]; +} + +$array = [ + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => [ + new \Zend\Validator\InArray(['haystack' => array_keys($aSubjects)]), + ], + ]; + +$var = [ + 'ViewHelper', + ['Foo'], + 'Errors', + ]; + +$data = [ + 'first', + 'second', + 'third', + // Add more here + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$data = [ + 'first', + 'second' + //'third', + ]; + +$foo = [ + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ]; + +$foo = [ + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ]; + +$weightings = [ + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ]; + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} + +$ids = [ + '1', // Foo. + '13', // Bar. + ]; + +[ + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + } +]; + +[ + 'key1' => [ + '1', + '2', + ] +]; + +$var = [ + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ]; + +function test() : array +{ + return []; +} + +$fields = [ + 'id' => ['type' => 'INT'], + 'value' => ['type' => 'VARCHAR']]; + +get_current_screen()->add_help_tab( [ + 'id' => << false]; + +$x = [ + 'xxxx' => ['aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false], +]; + +$foo = ['foo' => ['bar1' => 1 + ,'bar2' => 1 + ,'bar3' => 1 + ,'bar4' => 1 + ,'bar5' => 1 + ] + ]; + +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], ['notverified', 'unverified'], true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ]; + + +$foo = foo( + [ + // comment + ] +); + +$foo = [ + << lorem( + 1 + ), 2 => 2, +]; + +$foo = [ + 'тип' => 'авто', + 'цвет' => 'синий', + ]; + +$paths = [ + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ]; + +$foo = [<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ]; + +$array = [ + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ]; + +$foo = [ + $this->fn => 'value', + $foo->fn => 'value', + ]; + +[$a, $b, +$c]; + +['a' => $a, 'b' => $b, +'c' => $c]; + +[ + static function() { + return null; + }, + (array) [], + (bool) [], + (double) [], + (int) [], + (object) [], + (string) [], + (unset) [], +]; + +[ + 'foo', + 'bar' + // This is a non-fixable error. + , +]; + +yield [ + static fn () : string => '', +]; + +yield [ + static fn () : string => '', + ]; + +// Intentional syntax error. +$a = [ + 'a' => + ]; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed new file mode 100644 index 000000000..efe4c450e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed @@ -0,0 +1,504 @@ + 1]; +} + +class TestClass +{ + public $good = [ + 'width' => '', + 'height' => '', + ]; + + private $_bad = [ + 'width' => '', + 'height' => '', + ]; + + + public function test() + { + $truck = [ + 'width' => '', + 'height' => '', + ]; + + $plane = [ + 'width' => '', + 'height' => '', + ]; + + $car = [ + 'width' => '', + 'height' => '', + ]; + + $bus = [ + 'width' => '', + 'height' => '', + ]; + + $train = [ + TRUE, + FALSE, + 'aaa', + ]; + + $inline = [ + 'aaa', + 'bbb', + 'ccc', + ]; + $inline = ['aaa']; + $inline = ['aaa']; + + $bigone = [ + 'name' => 'bigone', + 'children' => [ + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => ['child' => 'aaa'], + ], + 'short_name' => 'big', + ]; + } + +}//end class + +$value = []; +$value = []; +$value = [ + '1' => $one, + '2' => $two, + '3' => $three, + '4' => $four, + ]; +$value = ['1' => $one]; + +if (in_array('1', ['1', '2', '3']) === TRUE) { + $value = in_array('1', ['1', '2', '3', '4']); +} + +$value = [ + '1'=> TRUE, + FALSE, + '3' => 'aaa', + ]; + +$value = [ + '1'=> TRUE, + FALSE, + ]; + +$value = [ + TRUE, + '1' => FALSE, + ]; + +$value = [ + 1, + 2, + 3, + ]; + +$value = [ + 1 => $one, + 2 => $two, + 3 => $three, + ]; + +$value = [ + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +// Space in second arg. +$args = [ + '"'.$this->id.'"', + (int) $hasSessions, + ]; + +// No errors. +$paths = [ + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ]; + +$x = []; + +$x = ['test']; +$x = ['test']; +$x = ['name' => 'test']; + +$x = [$x]; + +$func = [ + $x, + 'get'.$x.'Replacement', + ]; + +$array = [ + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ]; + +$array = [ + 'input_one', + 'inputTwo', + 'input_3', + ]; + +// Malformed +$foo = [ + 1, + 2, + ]; + +$listItems[$aliasPath] = ['itemContent' => implode('
    ', $aliases)]; + +$listItems[$aliasPath] = [ + 'itemContent' => implode('
    ', $aliases), + ]; + +$x = + [ + $x, + $y, + ]; + +$x = +[ + $x, + $y, +]; + +$x = [ + + $x, + $y, + ]; + +$test = [ + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ]; + +$c = ['a' => 1]; +$c->{$var}[ ] = 2; + +$foo = [ + '[', + ']', + ':', + "\n", + "\r", + ]; +$bar = [ + '[', + ']', + ':', + ' ', + ' ', + ]; + +function foo() +{ + return [ + $a, + $b->screen, + ]; +} + +$array = [ + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => [ + new \Zend\Validator\InArray(['haystack' => array_keys($aSubjects)]), + ], + ]; + +$var = [ + 'ViewHelper', + ['Foo'], + 'Errors', + ]; + +$data = [ + 'first', + 'second', + 'third', + // Add more here + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$foo = [ + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ]; + +$foo = [ + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ]; + +$weightings = [ + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ]; + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} + +$ids = [ + '1', // Foo. + '13', // Bar. + ]; + +[ + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + }, +]; + +[ + 'key1' => [ + '1', + '2', + ], +]; + +$var = [ + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ]; + +function test() : array +{ + return []; +} + +$fields = [ + 'id' => ['type' => 'INT'], + 'value' => ['type' => 'VARCHAR'], + ]; + +get_current_screen()->add_help_tab( [ + 'id' => << false]; + +$x = [ + 'xxxx' => [ + 'aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false, + ], + ]; + +$foo = [ + 'foo' => [ + 'bar1' => 1, + 'bar2' => 1, + 'bar3' => 1, + 'bar4' => 1, + 'bar5' => 1, + ], + ]; + +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], ['notverified', 'unverified'], true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ]; + + +$foo = foo( + [ + // comment + ] +); + +$foo = [ + << lorem( + 1 + ), + 2 => 2, +]; + +$foo = [ + 'тип' => 'авто', + 'цвет' => 'синий', + ]; + +$paths = [ + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'синий', + ]; + +$foo = [<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ]; + +$array = [ + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ]; + +$foo = [ + $this->fn => 'value', + $foo->fn => 'value', + ]; + +[ + $a, + $b, + $c, +]; + +[ + 'a' => $a, + 'b' => $b, + 'c' => $c, +]; + +[ + static function() { + return null; + }, + (array) [], + (bool) [], + (double) [], + (int) [], + (object) [], + (string) [], + (unset) [], +]; + +[ + 'foo', + 'bar' + // This is a non-fixable error. + , +]; + +yield [ + static fn () : string => '', + ]; + +yield [ + static fn () : string => '', + ]; + +// Intentional syntax error. +$a = [ + 'a' => + ]; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php new file mode 100644 index 000000000..15ce0746e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php @@ -0,0 +1,236 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Arrays; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ArrayDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ArrayDeclarationUnitTest.1.inc': + return [ + 2 => 1, + 8 => 2, + 10 => 2, + 22 => 1, + 23 => 2, + 24 => 2, + 25 => 1, + 31 => 2, + 35 => 1, + 36 => 2, + 41 => 1, + 46 => 1, + 47 => 1, + 50 => 1, + 51 => 1, + 53 => 1, + 56 => 1, + 58 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 3, + 70 => 1, + 76 => 2, + 77 => 1, + 78 => 7, + 79 => 2, + 81 => 2, + 82 => 4, + 87 => 1, + 88 => 1, + 92 => 1, + 97 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 125 => 1, + 126 => 1, + 141 => 1, + 144 => 1, + 146 => 1, + 148 => 1, + 151 => 1, + 157 => 1, + 173 => 1, + 174 => 3, + 179 => 1, + 182 => 1, + 188 => 1, + 207 => 1, + 212 => 2, + 214 => 1, + 218 => 2, + 219 => 2, + 223 => 1, + 255 => 1, + 294 => 1, + 295 => 1, + 296 => 1, + 311 => 1, + 317 => 1, + 339 => 2, + 348 => 2, + 352 => 2, + 355 => 3, + 358 => 3, + 359 => 2, + 360 => 1, + 362 => 1, + 363 => 2, + 364 => 1, + 365 => 2, + 366 => 2, + 367 => 2, + 368 => 2, + 369 => 1, + 370 => 1, + 383 => 1, + 394 => 1, + 400 => 1, + 406 => 1, + 441 => 1, + 444 => 2, + 445 => 2, + 447 => 2, + 448 => 3, + 467 => 1, + 471 => 1, + 472 => 1, + ]; + case 'ArrayDeclarationUnitTest.2.inc': + return [ + 2 => 1, + 10 => 1, + 23 => 2, + 24 => 2, + 25 => 1, + 31 => 2, + 36 => 2, + 41 => 1, + 46 => 1, + 47 => 1, + 51 => 1, + 53 => 1, + 56 => 1, + 61 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 2, + 70 => 1, + 76 => 1, + 77 => 1, + 78 => 7, + 79 => 2, + 81 => 2, + 82 => 4, + 87 => 1, + 88 => 1, + 92 => 1, + 97 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 125 => 1, + 126 => 1, + 141 => 1, + 144 => 1, + 146 => 1, + 148 => 1, + 151 => 1, + 157 => 1, + 173 => 1, + 174 => 3, + 179 => 1, + 190 => 1, + 191 => 1, + 192 => 1, + 207 => 1, + 210 => 1, + 211 => 1, + 215 => 1, + 247 => 1, + 286 => 1, + 287 => 1, + 288 => 1, + 303 => 1, + 309 => 1, + 331 => 2, + 345 => 3, + 348 => 3, + 349 => 2, + 350 => 1, + 352 => 2, + 353 => 2, + 354 => 2, + 355 => 2, + 356 => 2, + 357 => 1, + 358 => 1, + 372 => 1, + 383 => 1, + 389 => 1, + 395 => 1, + 430 => 1, + 433 => 2, + 434 => 2, + 436 => 2, + 437 => 3, + 456 => 1, + 460 => 1, + 461 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css new file mode 100644 index 000000000..39abce232 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css @@ -0,0 +1,81 @@ +.my-style { +} + + +.my-style { +} + +/* Comment */ + +.my-style { +} + + +/* Comment */ + +.my-style { + float: left; + +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +/*.AssetLineageWidgetType-item2 .selected, +.AssetLineageWidgetType-item .selected { +}*/ + +.AssetLineageWidgetType-item.selected { +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } +} + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + .no-blank-line-after { + } + .no-blank-line-after-second-def { + } .my-style { + } + + .no-blank-line-and-trailing-comment { + } /* end long class */ + .too-many-blank-lines-and-trailing-comment-extra-whitespace-after-brace { + } /* end long class */ + + + + .has-blank-line-and-trailing-comment { + } /* end long class */ + + .no-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + .too-many-blank-lines-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + + + .has-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%;}} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed new file mode 100644 index 000000000..ca77e83b6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed @@ -0,0 +1,85 @@ +.my-style { +} + +.my-style { +} + +/* Comment */ + +.my-style { +} + +/* Comment */ + +.my-style { + float: left; + +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +/*.AssetLineageWidgetType-item2 .selected, +.AssetLineageWidgetType-item .selected { +}*/ + +.AssetLineageWidgetType-item.selected { +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after { +} + +@media screen and (max-device-width: 769px) { + .no-blank-line-after { + } + + .no-blank-line-after-second-def { + } + +.my-style { + } + + .no-blank-line-and-trailing-comment { + } /* end long class */ + + .too-many-blank-lines-and-trailing-comment-extra-whitespace-after-brace { + } /* end long class */ + + .has-blank-line-and-trailing-comment { + } /* end long class */ + + .no-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + .too-many-blank-lines-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + .has-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; +} + +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php new file mode 100644 index 000000000..528fcfd6f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDefinitionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 11 => 1, + 44 => 1, + 47 => 1, + 51 => 1, + 53 => 1, + 57 => 1, + 59 => 1, + 67 => 1, + 69 => 1, + 81 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css new file mode 100644 index 000000000..6496cb839 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css @@ -0,0 +1,66 @@ +.AssetListingEditWidgetType-BottomPanel select, +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, + +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, +/*.AssetListingEditWidgetType-BottomPanel ul,*/ +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, + +.AssetListingEditWidgetType-BottomPanel ul, +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +#SuperUsersSystemConfigScreen-table { + display: block; + left: 50%; + margin-left: -500px; + margin-top: 180px; + position: relative; + width: 1000px; +} + +/** + * More styles below here. + */ + +td.TableWidgetType-header.TableWidgetType-header-lastLogin, +td.TableWidgetType-header.TableWidgetType-header-remove, +td.TableWidgetType-header.TableWidgetType-header-email, +td.TableWidgetType-header.TableWidgetType-header-userName { + background: url(images/ScreenImages/table_header_bg.png) repeat-x; + border-top: 1px solid #D4D4D4; + color: #787878; + height: 33px; + padding-left: 12px; + width: 150px; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +.foo +{ + border: none; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php new file mode 100644 index 000000000..41202bc8d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDefinitionNameSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 19 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css new file mode 100644 index 000000000..98c8fa563 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css @@ -0,0 +1,108 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title{ + float: left; +} +.HelpWidgetType-new-bug-title { + + float: left; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after {} + +.single-line {float: left;} + +#opening-brace-on-different-line + + +{ + color: #FFFFFF; +} + +#opening-brace-on-different-line-and-inline-style + + +{color: #FFFFFF;} + +@media screen and (max-device-width: 769px) { .everything-on-one-line { float: left; } } + +/* Document handling of comments in various places */ +.no-space-before-opening-with-comment /* comment*/{ + float: left; +} + +.space-before-opening-with-comment-on-next-line +/* comment*/ { + float: left; +} + +#opening-brace-on-different-line-with-comment-between +/*comment*/ +{ + padding: 0; +} + +.single-line-with-comment { /* comment*/ float: left; } + +.multi-line-with-trailing-comment { /* comment*/ + float: left; +} + + +@media screen and (max-device-width: 769px) { + /*comment*/ + .comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .blank-line-and-comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + + + /* phpcs:ignore Standard.Category.Sniffname -- for reasons */ + .blank-line-and-annotation-after-nesting-class-opening { + } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed new file mode 100644 index 000000000..b3f48a5ce --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed @@ -0,0 +1,106 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + + float: left; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after { +} + +.single-line { +float: left;} + +#opening-brace-on-different-line { + color: #FFFFFF; +} + +#opening-brace-on-different-line-and-inline-style { +color: #FFFFFF;} + +@media screen and (max-device-width: 769px) { + +.everything-on-one-line { +float: left; } } + +/* Document handling of comments in various places */ +.no-space-before-opening-with-comment /* comment*/ { + float: left; +} + +.space-before-opening-with-comment-on-next-line +/* comment*/ { + float: left; +} + +#opening-brace-on-different-line-with-comment-between +/*comment*/ { + padding: 0; +} + +.single-line-with-comment { +/* comment*/ float: left; } + +.multi-line-with-trailing-comment { /* comment*/ + float: left; +} + + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .blank-line-and-comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /* phpcs:ignore Standard.Category.Sniffname -- for reasons */ + .blank-line-and-annotation-after-nesting-class-opening { + } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php new file mode 100644 index 000000000..d1e44219c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDefinitionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 7 => 1, + 10 => 1, + 26 => 1, + 33 => 1, + 43 => 1, + 45 => 1, + 50 => 1, + 57 => 2, + 59 => 2, + 62 => 1, + 73 => 1, + 77 => 1, + 84 => 1, + 97 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css new file mode 100644 index 000000000..391bc85ac --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css @@ -0,0 +1,42 @@ +body { +font-family: Arial, Helvetica, sans-serif; +margin : 40px 0 0 0; +padding : 0; +background: #8FB7DB url(diag_lines_bg.gif) top left; +margin-top: +10px; +margin-bottom: +0px; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited { + text-decoration: none; + color: #444; +} + +/* checking embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; + margin:0px; + padding-left:10px; + margin-bottom:px; + margin-top: px; + line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Empty style defs. */ +.p { + margin:; + margin-right: + margin-left: 10px; + float:/* Some comment. */ ; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed new file mode 100644 index 000000000..e68bddce6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed @@ -0,0 +1,40 @@ +body { +font-family: Arial, Helvetica, sans-serif; +margin: 40px 0 0 0; +padding: 0; +background: #8FB7DB url(diag_lines_bg.gif) top left; +margin-top: 10px; +margin-bottom: 0px; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited { + text-decoration: none; + color: #444; +} + +/* checking embedded PHP */ +li { + background: url(/images//bullet.gif) left px no-repeat; + margin: 0px; + padding-left: 10px; + margin-bottom: px; + margin-top: px; + line-height: 13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Empty style defs. */ +.p { + margin:; + margin-right: + margin-left: 10px; + float: /* Some comment. */ ; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php new file mode 100644 index 000000000..9b8aa1030 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ColonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 2, + 5 => 1, + 6 => 1, + 8 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + 41 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css new file mode 100644 index 000000000..2dfd22adb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css @@ -0,0 +1,16 @@ +#title-bar-bottom-right { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #08f7db url(diag_lines_bg.gif) top left; + + /* The sniff only deals with HEX colours. */ + color: DarkSlateGray; + background-color: rgb(255, 0, 0); + background-color: rgba(0, 0, 255, 0.3); + background-color: hsl(120, 100%, 50%); +} + +#add-new-comment { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed new file mode 100644 index 000000000..039209dd5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed @@ -0,0 +1,16 @@ +#title-bar-bottom-right { + background-color: #333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #F0F; + background: #08F7DB url(diag_lines_bg.gif) top left; + + /* The sniff only deals with HEX colours. */ + color: DarkSlateGray; + background-color: rgb(255, 0, 0); + background-color: rgba(0, 0, 255, 0.3); + background-color: hsl(120, 100%, 50%); +} + +#add-new-comment { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php new file mode 100644 index 000000000..d535fdc2e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ColourDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 6 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css new file mode 100644 index 000000000..4c11beaa8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css @@ -0,0 +1,17 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + height: 100%;float: left; + line-height: -25px; + cursor: pointer; margin: 10px; float: right; +} + +/* testing embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; margin:0px; padding-left:10px; margin-bottom:px; line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Document handling of comments and annotations. */ +div#annotations {-webkit-tap-highlight-color:transparent;/* phpcs:disable Standard.Cat.SniffName */-webkit-touch-callout:none;/*phpcs:enable*/-webkit-user-select:none;} + +div#comments {height:100%;/*comment*/width:100%;} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed new file mode 100644 index 000000000..93a7815e6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed @@ -0,0 +1,27 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + height: 100%; +float: left; + line-height: -25px; + cursor: pointer; +margin: 10px; +float: right; +} + +/* testing embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; +margin:0px; +padding-left:10px; +margin-bottom:px; +line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Document handling of comments and annotations. */ +div#annotations {-webkit-tap-highlight-color:transparent;/* phpcs:disable Standard.Cat.SniffName */ +-webkit-touch-callout:none;/*phpcs:enable*/ +-webkit-user-select:none;} + +div#comments {height:100%;/*comment*/ +width:100%;} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php new file mode 100644 index 000000000..8e3b48738 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowMultipleStyleDefinitionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 2, + 10 => 4, + 15 => 2, + 17 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css new file mode 100644 index 000000000..8ac95012a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css @@ -0,0 +1,103 @@ +.AssetLineageWidgetType-item { + color: #FFF; +} + +.AssetLineageWidgetType-title { + color: #CCC; +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +.AssetLineageWidgetType-item .selected { +} + +.AssetLineageWidgetType-item.selected { +} + +#Blah .AssetLineageWidgetType-item { +} + +#X.selected, +.AssetLineageWidgetType-item { +} + +.MyClass, .YourClass { +} + +.YourClass, .MyClass { +} + +.YourClass, .MyClass, .OurClass { +} + + +.ClassAtTopOfMediaBlock { +} + +@media print { + .ClassAtTopOfMediaBlock { + } + + .ClassInMultipleMediaBlocks { + } +} + +.ClassNotAtTopOfMediaBlock { +} + +@media handheld { + .SameClassInMediaBlock { + } + + .ClassNotAtTopOfMediaBlock { + } + + .SameClassInMediaBlock { + } +} + +@media braille { + .PlaceholderClass { + } + + .ClassNotAtTopOfMediaBlock { + } + + .ClassInMultipleMediaBlocks { + } +} + +.foo /* any comment */ +{ color: red; } + +/* print comment */ +@media print { + /* comment1 */ + td { + } + + /* comment2 */ + img { + } + + /* comment3 */ + td { + } +} + +@media handheld /* handheld comment */ +{ + td /* comment1 */ + { + } + + img /* comment2 */ + { + } + + td /* comment3 */ + { + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php new file mode 100644 index 000000000..2a95971b0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DuplicateClassDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 29 => 1, + 57 => 1, + 86 => 1, + 101 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css new file mode 100644 index 000000000..c9c849f61 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css @@ -0,0 +1,27 @@ +.ViperSubToolbar-wrapper { + height: 34px; + left: 0; + position: fixed; + top: 60px; + z-index: 997; + left: 50%; +} + +.expandable { + -moz-transition-property: margin-left, margin-right; + -moz-transition-duration: 0.2s; + -moz-transition-timing-function: ease; + -webkit-transition-property: margin-left, margin-right; + -webkit-transition-duration: 0.2s; + -webkit-transition-timing-function: ease; + z-index: 2; +} + +@media only screen and (max-width: 480px) { + header nav.meta a { display: none; } + header nav.meta a.search { display: block; } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php new file mode 100644 index 000000000..c555461b1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DuplicateStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [7 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css new file mode 100644 index 000000000..801dcda11 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css @@ -0,0 +1,15 @@ +.HelpWidgetType-new-bug-title {} +.HelpWidgetType-new-bug-title { +} +.HelpWidgetType-new-bug-title { + +} +.HelpWidgetType-new-bug-title { + +} +.HelpWidgetType-new-bug-title { + /* Nothing to see here */ +} +.HelpWidgetType-new-bug-title { + float: left; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php new file mode 100644 index 000000000..b3fd318c9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmptyClassDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 1 => 1, + 2 => 1, + 4 => 1, + 7 => 1, + 10 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css new file mode 100644 index 000000000..24910b714 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css @@ -0,0 +1,11 @@ +#MetadataAdminScreen-addField-fieldType { + margin-left: 10px; + margin-right: + float: ; +} + +#MetadataAdminScreen-addField-fieldType li { + margin-right: /* @todo */ + margin-left: 10px; + float: /* Some comment. */ ; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php new file mode 100644 index 000000000..f5bc858d0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmptyStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 8 => 1, + 10 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css new file mode 100644 index 000000000..dbd548705 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css @@ -0,0 +1,18 @@ +#add-new-comment { + -moz-border-radius: 1px; + -webkit-border-radius: 1px; + border-radius: 1px; + + -moz-border-radius-topleft: 1px; + -moz-border-radius-topright: 1px; + -moz-border-radius-bottomright: 1px; + -moz-border-radius-bottomleft: 1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + + -moz-box-shadow: 1px; + -webkit-box-shadow: 1px; + box-shadow: 1px; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed new file mode 100644 index 000000000..a8ea27048 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed @@ -0,0 +1,18 @@ +#add-new-comment { + border-radius: 1px; + border-radius: 1px; + border-radius: 1px; + + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + + box-shadow: 1px; + box-shadow: 1px; + box-shadow: 1px; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php new file mode 100644 index 000000000..28aa8ec30 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForbiddenStylesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 15 => 1, + 16 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css new file mode 100644 index 000000000..216f00ee5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css @@ -0,0 +1,79 @@ +body { + + font-family: Arial, Helvetica, sans-serif; + margin: 40px 0 0 0; +padding: 0; + background: #8FB7DB url(diag_lines_bg.gif) top left; + +} + +td { + margin: 40px; + + padding: 20px; +} + +/* +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left { + background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat; +} +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right { + background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat; +} +*/ + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + + header #logo img { + min-width: 100%; + } + +} + +td { + margin: 40px; + + padding: 20px; + + +} + +.GUIFileUpload { +/* opacity: 0.25; */ +} + +.foo +{ + border: none; +} + +.mortgage-calculator h2 { + background: #072237; + color: #fff; + font-weight: normal; + height: 50px; + line-height: 50px; + padding: 0 0 0 30px; + } + +.WhitelistCommentIndentationShouldBeIgnored { +/* phpcs:disable Standard.Category.Sniff -- for reasons. */ +} + +/* syntax error */ +--------------------------------------------- */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed new file mode 100644 index 000000000..1fd128a5e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed @@ -0,0 +1,73 @@ +body { + font-family: Arial, Helvetica, sans-serif; + margin: 40px 0 0 0; + padding: 0; + background: #8FB7DB url(diag_lines_bg.gif) top left; +} + +td { + margin: 40px; + padding: 20px; +} + +/* +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left { + background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat; +} +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right { + background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat; +} +*/ + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + + header #logo img { + min-width: 100%; + } + +} + +td { + margin: 40px; + padding: 20px; +} + +.GUIFileUpload { +/* opacity: 0.25; */ +} + +.foo +{ + border: none; +} + +.mortgage-calculator h2 { + background: #072237; + color: #fff; + font-weight: normal; + height: 50px; + line-height: 50px; + padding: 0 0 0 30px; +} + +.WhitelistCommentIndentationShouldBeIgnored { +/* phpcs:disable Standard.Category.Sniff -- for reasons. */ +} + +/* syntax error */ +--------------------------------------------- */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css new file mode 100644 index 000000000..48b22f6d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css @@ -0,0 +1,3 @@ +/* Live coding. Has to be the last (only) test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php new file mode 100644 index 000000000..9413b4ffb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IndentationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'IndentationUnitTest.1.css': + return [ + 2 => 1, + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 12 => 1, + 30 => 1, + 32 => 1, + 50 => 1, + 52 => 1, + 53 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css new file mode 100644 index 000000000..d0f2982fb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css @@ -0,0 +1,14 @@ +.SettingsTabPaneWidgetType-tab-mid { + font-family: Arial; + Font-Family: arial; + background-color: #DA9393; + BACKGROUND-IMAGE: URL(Warning_Close.png); +} + +@media screen and (max-device-width: 769px) { + + .SettingsTabPaneWidgetType-tab-mid { + Font-Family: arial; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php new file mode 100644 index 000000000..1a25aaac8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 5 => 2, + 11 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css new file mode 100644 index 000000000..6c947e5b5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css @@ -0,0 +1,21 @@ +.my-style { + margin-right 15px; + float: left; + margin-left 15px; + margin-top: 15px; + margin-bottom 15px; +} + +@media screen and (max-device-width: 769px) { + header #logo img { + max-width: 100%; + margin-bottom 15px; + } +} + +#foo { background-color: #FF0000; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php new file mode 100644 index 000000000..dc0809e26 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MissingColonUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 6 => 1, + 12 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css new file mode 100644 index 000000000..05637a602 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css @@ -0,0 +1,25 @@ +#red { + background-color: red; +} + +.red { + border-bottom: 1px dotted black; + border-top: 1px dotted gray; +} + +#red.yellow { + background: yellow url(diag_lines_bg.gif) top left; + text-shadow: 0 1px 0 white; +} + +.something--white { + border: 0; +} + +.something--------------white { + border: 0; +} + +.-white { + border: 0; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php new file mode 100644 index 000000000..a8032fad3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NamedColoursUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css new file mode 100644 index 000000000..c656c78ee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css @@ -0,0 +1,35 @@ +.my-style { + opacity: 0; + opacity: 0.0; + opacity: 1; + opacity: 1.0; + opacity: 1.5; + opacity: .5; + opacity: 0.5; + opacity: 2; + opacity: -1; + opacity: 0.55; +} + +div { + font-size: 1.2em; + background: linear-gradient(to bottom, #00F, #0F0) repeat scroll 50% 50% #EEE; + min-width: 250px; + max-width: 100%; + padding-bottom: 50px; + box-shadow: 2px -3px 3px rgba(100, 100, 100, 0.33); + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 1px solid #000; + border-bottom: 1px dotted #000; + background: url(../1/2/3/4-5-6_7_100x100.png) repeat scroll 50% 50% #EEE; + opacity: -1; +} + +.my-commented-style { + opacity: /*comment*/ 0; + opacity: /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + 0.0; + opacity: /*comment*/ 1.0; + opacity: /*comment*/ .5; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed new file mode 100644 index 000000000..257e41a78 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed @@ -0,0 +1,35 @@ +.my-style { + opacity: 0; + opacity: 0; + opacity: 1; + opacity: 1; + opacity: 1.5; + opacity: 0.5; + opacity: 0.5; + opacity: 2; + opacity: -1; + opacity: 0.55; +} + +div { + font-size: 1.2em; + background: linear-gradient(to bottom, #00F, #0F0) repeat scroll 50% 50% #EEE; + min-width: 250px; + max-width: 100%; + padding-bottom: 50px; + box-shadow: 2px -3px 3px rgba(100, 100, 100, 0.33); + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 1px solid #000; + border-bottom: 1px dotted #000; + background: url(../1/2/3/4-5-6_7_100x100.png) repeat scroll 50% 50% #EEE; + opacity: -1; +} + +.my-commented-style { + opacity: /*comment*/ 0; + opacity: /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + 0; + opacity: /*comment*/ 1; + opacity: /*comment*/ 0.5; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php new file mode 100644 index 000000000..9fe839da5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OpacityUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 26 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css new file mode 100644 index 000000000..3ccb162e8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css @@ -0,0 +1,61 @@ +.HelpWidgetType-new-bug-title { + width: 308px + float: left; +} + +#MetadataAdminScreen-addField-add { + float: left ; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.HelpWidgetType-list { + list-style-image: url(); +} + +@media (min-width: 320px) and (max-width: 961px) { + .tooltipsrt:hover span.tltp, + .tooltipstp:hover span.tltp { + visibility: hidden; + } +} + +#single-line-multi-statement-no-semicolon { + padding: 0 border: 20; +} + +#multi-line-style-no-semicolon { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20 + margin: + 0px /* top */ + 10px /* right + left */ +} + +#multi-line-style-whitespace { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ ; + border: + 20 ; + margin: + 10px /* top */ + 0px /* right + left */ + + + ; +} + +.allow-for-star-hack { + cursor: pointer; + *cursor: hand; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed new file mode 100644 index 000000000..7efef5882 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed @@ -0,0 +1,58 @@ +.HelpWidgetType-new-bug-title { + width: 308px + float: left; +} + +#MetadataAdminScreen-addField-add { + float: left; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.HelpWidgetType-list { + list-style-image: url(); +} + +@media (min-width: 320px) and (max-width: 961px) { + .tooltipsrt:hover span.tltp, + .tooltipstp:hover span.tltp { + visibility: hidden; + } +} + +#single-line-multi-statement-no-semicolon { + padding: 0 border: 20; +} + +#multi-line-style-no-semicolon { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20 + margin: + 0px /* top */ + 10px /* right + left */ +} + +#multi-line-style-whitespace { + padding: 0; /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20; + margin: + 10px /* top */ + 0px; /* right + left */ +} + +.allow-for-star-hack { + cursor: pointer; + *cursor: hand; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php new file mode 100644 index 000000000..897df65ec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SemicolonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 7 => 1, + 30 => 1, + 34 => 1, + 36 => 1, + 39 => 1, + 43 => 1, + 45 => 1, + 48 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css new file mode 100644 index 000000000..cfc4503c4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css @@ -0,0 +1,45 @@ +#add-new-comment { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #8fb7db url(diag_lines_bg.gif) top left; + tab-size: 1; + margin: 8px 8px 8px 8px; + margin: 8px 8px; + margin: 0 0 0 0; + margin: 0 8px 0 8px; + margin: 8px 4px 8px 4px; + margin: 8px 4% 8px 4%; + margin: 6px 2px 9px 2px; + margin: 6px 2px 9px; + border-radius: 2px 2px 2px 2px !important; + border-width: 2px 2px 2px 2px; + border-width: 1px 2px 2px 4px; + margin: 97px auto 0 auto; + text-shadow: 0 1px 0 #fff; + border-width: + 2px + 4px + 2px + 4px; + + /* These are style names excluded from this rule. */ + background-position: 0 0; + box-shadow: 2px 2px 2px 2px; + transform-origin: 0 110% 0; + + /* Sizes with comments between them will be ignored for the purposes of this sniff. */ + margin: 8px /*top*/ 8px /*right*/ 8px /*bottom*/ 8px /*left*/; + + /* Same with PHPCS annotations. */ + border-width: + 2px /* phpcs:ignore Standard.Category.SniffName -- for reasons */ + 4px + 2px /* phpcs:disable Standard.Category.SniffName -- for reasons */ + 4px; +} + +/* Intentional parse error. Live coding resilience. This has to be the last test in the file. */ +#live-coding { + margin: 8px 8px 8px 8px diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed new file mode 100644 index 000000000..3472cb174 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css.fixed @@ -0,0 +1,41 @@ +#add-new-comment { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #8fb7db url(diag_lines_bg.gif) top left; + tab-size: 1; + margin: 8px; + margin: 8px; + margin: 0; + margin: 0 8px; + margin: 8px 4px; + margin: 8px 4%; + margin: 6px 2px 9px 2px; + margin: 6px 2px 9px 2px; + border-radius: 2px !important; + border-width: 2px; + border-width: 1px 2px 2px 4px; + margin: 97px auto 0 auto; + text-shadow: 0 1px 0 #fff; + border-width: 2px 4px; + + /* These are style names excluded from this rule. */ + background-position: 0 0; + box-shadow: 2px 2px 2px 2px; + transform-origin: 0 110% 0; + + /* Sizes with comments between them will be ignored for the purposes of this sniff. */ + margin: 8px /*top*/ 8px /*right*/ 8px /*bottom*/ 8px /*left*/; + + /* Same with PHPCS annotations. */ + border-width: + 2px /* phpcs:ignore Standard.Category.SniffName -- for reasons */ + 4px + 2px /* phpcs:disable Standard.Category.SniffName -- for reasons */ + 4px; +} + +/* Intentional parse error. Live coding resilience. This has to be the last test in the file. */ +#live-coding { + margin: 8px 8px 8px 8px diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php new file mode 100644 index 000000000..3d0baaade --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ShorthandSizeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 21 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc new file mode 100644 index 000000000..43ef6c9cd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc @@ -0,0 +1,121 @@ + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 6 => 1, + 10 => 1, + 15 => 2, + 18 => 1, + 22 => 4, + 23 => 4, + 24 => 4, + 27 => 2, + 30 => 2, + 34 => 1, + 35 => 1, + 39 => 1, + 42 => 1, + 45 => 1, + 48 => 1, + 50 => 2, + 51 => 1, + 55 => 1, + 59 => 4, + 63 => 1, + 65 => 1, + 69 => 3, + 74 => 2, + 77 => 1, + 80 => 1, + 85 => 3, + 89 => 1, + 92 => 1, + 97 => 1, + 108 => 1, + 114 => 1, + 116 => 1, + 118 => 1, + 121 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc new file mode 100644 index 000000000..8b5a5aa70 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc @@ -0,0 +1,45 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php new file mode 100644 index 000000000..5964d2b1e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassFileNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js new file mode 100644 index 000000000..04126f86a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js @@ -0,0 +1,45 @@ +var x = { + abc: 1, + zyz: 2, + abc: 5, + mno: { + abc: 4 + }, + abc: 5 + + this.request({ + action: 'getSubmissions' + }); + + this.request({ + action: 'deleteSubmission' + }); +} + + +LinkingEditScreenWidgetType.prototype = { + + _addDeleteButtonEvent: function(parentid) + { + var params = { + screen: 'LinkingEditScreenWidget', + assetid: self.assetid, + parentid: parentid, + assetid: parentid, + op: 'deleteLink' + }; + + }, + + saveDesignEdit: function() + { + var params = { + screen: [this.id, 'Widget'].join(''), + assetid: this.assetid, + changes: dfx.jsonEncode(this.currnetLinksWdgt.getChanges()), + op: 'saveLinkEdit' + }; + + } + +}; \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php new file mode 100644 index 000000000..1b71eb2c6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DuplicatePropertyUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 8 => 1, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc new file mode 100644 index 000000000..ea8cd89ec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseClassKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 2 => 3, + 3 => 3, + 4 => 1, + 5 => 1, + 6 => 2, + 10 => 1, + 11 => 1, + 14 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc new file mode 100644 index 000000000..0a0729a0a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc @@ -0,0 +1,174 @@ +testResults; + + + // Correct call to self. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = parent::selfMemberReferenceUnitTestFunction(); + + // Incorrect case. + $testResults[] = Self::selfMemberReferenceUnitTestFunction(); + $testResults[] = SELF::selfMemberReferenceUnitTestFunction(); + $testResults[] = SelfMemberReferenceUnitTestExample::selfMemberReferenceUnitTestFunction(); + + + // Incorrect spacing. + $testResults[] = self ::selfMemberReferenceUnitTestFunction(); + $testResults[] = self:: selfMemberReferenceUnitTestFunction(); + $testResults[] = self :: selfMemberReferenceUnitTestFunction(); + + // Remove ALL the newlines + $testResults[] = self + + + + + :: + + + + + selfMemberReferenceUnitTestFunction(); + + } + + + function selfMemberReferenceUnitTestFunction() + { + $this->testCount = $this->testCount + 1; + return $this->testCount; + + } + + +} + + +class MyClass { + + public static function test($value) { + echo "$value\n"; + } + + public static function walk() { + $callback = function($value, $key) { + // This is valid because you can't use self:: in a closure. + MyClass::test($value); + }; + + $array = array(1,2,3); + array_walk($array, $callback); + } +} + +MyClass::walk(); + +class Controller +{ + public function Action() + { + Doctrine\Common\Util\Debug::dump(); + } +} + +class Foo +{ + public static function bar() + { + \Foo::baz(); + } +} + +namespace TYPO3\CMS\Reports; + +class Status { + const NOTICE = -2; + const INFO = -1; + const OK = 0; + const WARNING = 1; + const ERROR = 2; +} + +namespace TYPO3\CMS\Reports\Report\Status; + +class Status implements \TYPO3\CMS\Reports\ReportInterface { + public function getHighestSeverity(array $statusCollection) { + $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE; + } +} + +namespace Foo; + +class Bar { + + function myFunction() + { + \Foo\Whatever::something(); + \Foo\Bar::something(); + } +} + +namespace Foo\Bar; + +class Baz { + + function myFunction() + { + \Foo\Bar\Whatever::something(); + \Foo\Bar\Baz::something(); + } +} + +class Nested_Anon_Class { + public function getAnonymousClass() { + // Spacing/comments should not cause false negatives for the NotUsed error. + Nested_Anon_Class :: $prop; + Nested_Anon_Class + /* some comment */ + + :: + + // phpcs:ignore Standard.Category.SniffName -- for reasons. + Bar(); + + // Anonymous class is a different scope. + return new class() { + public function nested_function() { + Nested_Anon_Class::$prop; + Nested_Anon_Class::BAR; + } + }; + } +} + +// Test dealing with scoped namespaces. +namespace Foo\Baz { + class BarFoo { + public function foo() { + echo Foo\Baz\BarFoo::$prop; + } + } +} + +// Prevent false negative when namespace has whitespace/comments. +namespace Foo /*comment*/ \ Bah { + class BarFoo { + public function foo() { + echo Foo \ /*comment*/ Bah\BarFoo::$prop; + } + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed new file mode 100644 index 000000000..f2c1731dc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed @@ -0,0 +1,162 @@ +testResults; + + + // Correct call to self. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = parent::selfMemberReferenceUnitTestFunction(); + + // Incorrect case. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + + // Incorrect spacing. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + // Remove ALL the newlines + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + } + + + function selfMemberReferenceUnitTestFunction() + { + $this->testCount = $this->testCount + 1; + return $this->testCount; + + } + + +} + + +class MyClass { + + public static function test($value) { + echo "$value\n"; + } + + public static function walk() { + $callback = function($value, $key) { + // This is valid because you can't use self:: in a closure. + MyClass::test($value); + }; + + $array = array(1,2,3); + array_walk($array, $callback); + } +} + +MyClass::walk(); + +class Controller +{ + public function Action() + { + Doctrine\Common\Util\Debug::dump(); + } +} + +class Foo +{ + public static function bar() + { + self::baz(); + } +} + +namespace TYPO3\CMS\Reports; + +class Status { + const NOTICE = -2; + const INFO = -1; + const OK = 0; + const WARNING = 1; + const ERROR = 2; +} + +namespace TYPO3\CMS\Reports\Report\Status; + +class Status implements \TYPO3\CMS\Reports\ReportInterface { + public function getHighestSeverity(array $statusCollection) { + $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE; + } +} + +namespace Foo; + +class Bar { + + function myFunction() + { + \Foo\Whatever::something(); + self::something(); + } +} + +namespace Foo\Bar; + +class Baz { + + function myFunction() + { + \Foo\Bar\Whatever::something(); + self::something(); + } +} + +class Nested_Anon_Class { + public function getAnonymousClass() { + // Spacing/comments should not cause false negatives for the NotUsed error. + self::$prop; + + /* some comment */ + + self::// phpcs:ignore Standard.Category.SniffName -- for reasons. + Bar(); + + // Anonymous class is a different scope. + return new class() { + public function nested_function() { + Nested_Anon_Class::$prop; + Nested_Anon_Class::BAR; + } + }; + } +} + +// Test dealing with scoped namespaces. +namespace Foo\Baz { + class BarFoo { + public function foo() { + echo self::$prop; + } + } +} + +// Prevent false negative when namespace has whitespace/comments. +namespace Foo /*comment*/ \ Bah { + class BarFoo { + public function foo() { + echo /*comment*/ self::$prop; + } + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php new file mode 100644 index 000000000..ea493d3cb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SelfMemberReferenceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 24 => 1, + 25 => 1, + 26 => 1, + 30 => 1, + 31 => 1, + 32 => 2, + 40 => 2, + 92 => 1, + 121 => 1, + 132 => 1, + 139 => 3, + 140 => 1, + 143 => 2, + 162 => 1, + 171 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc new file mode 100644 index 000000000..3fe39435b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc @@ -0,0 +1,191 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +// Valid interface name. +interface ValidCamelCaseClass extends MyClass {} + + +// Incorrect usage of camel case. +interface invalidCamelCaseClass extends MyClass {} +interface Invalid_Camel_Case_Class_With_Underscores implements MyClass {} + + +// All lowercase. +interface invalidlowercaseclass extends MyClass {} +interface invalid_lowercase_class_with_underscores extends MyClass {} + + +// All uppercase. +interface VALIDUPPERCASECLASS extends MyClass {} +interface INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {} + + +// Mix camel case with uppercase. +interface ValidCamelCaseClassWithUPPERCASE extends MyClass {} + + +// Usage of numeric characters. +interface ValidCamelCaseClassWith1Number extends MyClass {} +interface ValidCamelCaseClassWith12345Numbers extends MyClass {} +interface 5InvalidCamelCaseClassStartingWithNumber extends MyClass {} +interface ValidCamelCaseClassEndingWithNumber5 extends MyClass {} +interface 12345 extends MyClass {} + +interface Testing{} + +interface Base +{ + protected $anonymous; + + public function __construct(); +} + + +// Valid trait name. +trait ValidCamelCaseClass extends MyClass {} + + +// Incorrect usage of camel case. +trait invalidCamelCaseClass extends MyClass {} +trait Invalid_Camel_Case_Class_With_Underscores implements MyClass {} + + +// All lowercase. +trait invalidlowercaseclass extends MyClass {} +trait invalid_lowercase_class_with_underscores extends MyClass {} + + +// All uppercase. +trait VALIDUPPERCASECLASS extends MyClass {} +trait INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {} + + +// Mix camel case with uppercase. +trait ValidCamelCaseClassWithUPPERCASE extends MyClass {} + + +// Usage of numeric characters. +trait ValidCamelCaseClassWith1Number extends MyClass {} +trait ValidCamelCaseClassWith12345Numbers extends MyClass {} +trait 5InvalidCamelCaseClassStartingWithNumber extends MyClass {} +trait ValidCamelCaseClassEndingWithNumber5 extends MyClass {} +trait 12345 extends MyClass {} + +trait Testing{} + +trait Base +{ + protected $anonymous; + + public function __construct() + { + $this->anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +// Valid enum name. +enum ValidCamelCaseClass: string {} + + +// Incorrect usage of camel case. +enum invalidCamelCaseClass {} +enum Invalid_Camel_Case_Class_With_Underscores {} + + +// All lowercase. +enum invalidlowercaseclass: INT {} +enum invalid_lowercase_class_with_underscores {} + + +// All uppercase. +enum VALIDUPPERCASECLASS: int {} +enum INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES {} + + +// Mix camel case with uppercase. +enum ValidCamelCaseClassWithUPPERCASE : string {} + + +// Usage of numeric characters. +enum ValidCamelCaseClassWith1Number {} +enum ValidCamelCaseClassWith12345Numbers : string {} +enum ValidCamelCaseClassEndingWithNumber5 {} + +enum Testing{} + +enum Base +{ + public function __construct() + { + $this->anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +if ( class_exists( Test :: class ) ) {} +if ( class_exists( Test2 ::class ) ) {} + +$foo = new class( + new class implements Countable { + } +) extends DateTime { +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php new file mode 100644 index 000000000..b7de260b6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidClassNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 10 => 1, + 14 => 1, + 15 => 1, + 20 => 1, + 30 => 1, + 32 => 1, + 57 => 1, + 58 => 1, + 62 => 1, + 63 => 1, + 68 => 1, + 78 => 1, + 80 => 1, + 97 => 1, + 98 => 1, + 102 => 1, + 103 => 1, + 108 => 1, + 118 => 1, + 120 => 1, + 145 => 1, + 146 => 1, + 150 => 1, + 151 => 1, + 156 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc new file mode 100644 index 000000000..7cd04a211 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc @@ -0,0 +1,309 @@ + + + + + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class BlockCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 3 => 1, + 8 => 1, + 20 => 1, + 24 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 40 => 1, + 45 => 1, + 49 => 1, + 51 => 1, + 53 => 1, + 57 => 1, + 60 => 1, + 61 => 1, + 63 => 1, + 65 => 1, + 68 => 1, + 70 => 1, + 72 => 1, + 75 => 1, + 84 => 1, + 87 => 1, + 89 => 1, + 92 => 1, + 111 => 1, + 159 => 1, + 181 => 1, + 188 => 1, + 208 => 1, + 214 => 1, + 226 => 1, + 227 => 1, + 232 => 1, + 233 => 1, + 256 => 1, + 271 => 1, + 273 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc new file mode 100644 index 000000000..28aff226b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc @@ -0,0 +1,133 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClassCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 15 => 1, + 31 => 1, + 54 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 29 => 1, + 30 => 1, + 50 => 1, + 66 => 1, + 67 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc new file mode 100644 index 000000000..1a57149b2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingDeclarationCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 17 => 1, + 31 => 1, + 41 => 1, + 59 => 1, + 63 => 1, + 67 => 1, + 79 => 1, + 83 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [71 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc new file mode 100644 index 000000000..e42cf8ab2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc @@ -0,0 +1,103 @@ + line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +class MyClass2 +{ + /** + * Some info about the variable here. + */ + var $x; +} + +abstract class MyClass +{ + /** +* Property comment + */ + readonly public string $prop; +} + +/** + * Some info about the enum here + * +*/ +enum Suits: string +{ + /** + * Some info about the case here. + */ + case HEARTS; +} + +/** ************************************************************************ + * Example with no errors. + **************************************************************************/ +function example() {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed new file mode 100644 index 000000000..6182b539c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed @@ -0,0 +1,103 @@ + line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +class MyClass2 +{ + /** + * Some info about the variable here. + */ + var $x; +} + +abstract class MyClass +{ + /** + * Property comment + */ + readonly public string $prop; +} + +/** + * Some info about the enum here + * + */ +enum Suits: string +{ + /** + * Some info about the case here. + */ + case HEARTS; +} + +/** ************************************************************************ + * Example with no errors. + **************************************************************************/ +function example() {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js new file mode 100644 index 000000000..6e1a87812 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js @@ -0,0 +1,76 @@ + +/** +* Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + *@return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + *Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * +*/ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +function myFunction() +{ + console.info('hi'); + /** + Comment here. + */ +} + +/** + * Creates a map of tokens => line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +$.extend(Datepicker.prototype, { + _widgetDatepicker: function() { + }, + /* Action for selecting a new month/year. */ +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed new file mode 100644 index 000000000..9edb4ccc6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed @@ -0,0 +1,76 @@ + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +function myFunction() +{ + console.info('hi'); + /** + Comment here. + */ +} + +/** + * Creates a map of tokens => line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +$.extend(Datepicker.prototype, { + _widgetDatepicker: function() { + }, + /* Action for selecting a new month/year. */ +}); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php new file mode 100644 index 000000000..acbf13e86 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DocCommentAlignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DocCommentAlignmentUnitTest.inc') + { + $errors = [ + 3 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 23 => 2, + 24 => 1, + 25 => 2, + 26 => 1, + 32 => 1, + 33 => 1, + 38 => 1, + 39 => 1, + ]; + + if ($testFile === 'DocCommentAlignmentUnitTest.inc') { + $errors[75] = 1; + $errors[83] = 1; + $errors[84] = 1; + $errors[90] = 1; + $errors[91] = 1; + $errors[95] = 1; + $errors[96] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc new file mode 100644 index 000000000..cde6e462f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc @@ -0,0 +1,55 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php new file mode 100644 index 000000000..3c1668e44 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmptyCatchCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 33 => 1, + 49 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc new file mode 100644 index 000000000..1db2861b8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc @@ -0,0 +1,43 @@ + +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1994-1997 The PHP Group +* @copyright The PHP Group +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +?> + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed new file mode 100644 index 000000000..e42e037c7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed @@ -0,0 +1,43 @@ + +* @author +* @copyright 1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 1994-1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +?> + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js new file mode 100644 index 000000000..57d8d37a6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js @@ -0,0 +1,40 @@ + + + + +/** +* +* 0Multi-line short description without full stop +* +* +* asdasd +* long description for file (if any) +* asdasdadada +* +* PHP versio +* +* LICENSE: This source file is subject to version 3.0 of the PHP license +* that is available through the world-wide-web at the following URI: +* http://www.php.net/license/3_0.txt. If you did not receive a copy of +* the PHP License and are unable to obtain it through the web, please +* send a note to license@php.net so we can mail you a copy immediately. +* @package SquizCMS +* @package ADDITIONAL PACKAGE TAG +* @subpkg not_camelcased +* @author Antônio Carlos Venâncio Júnior +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1994-1997 The PHP Group +* @copyright The PHP Group +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +/** +* This bit here is not qualified as file comment +* +* as it is not the first comment in the file +* +*/ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed new file mode 100644 index 000000000..90046c710 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed @@ -0,0 +1,40 @@ + + + + +/** +* +* 0Multi-line short description without full stop +* +* +* asdasd +* long description for file (if any) +* asdasdadada +* +* PHP versio +* +* LICENSE: This source file is subject to version 3.0 of the PHP license +* that is available through the world-wide-web at the following URI: +* http://www.php.net/license/3_0.txt. If you did not receive a copy of +* the PHP License and are unable to obtain it through the web, please +* send a note to license@php.net so we can mail you a copy immediately. +* @package SquizCMS +* @package ADDITIONAL PACKAGE TAG +* @subpkg not_camelcased +* @author Squiz Pty Ltd +* @author +* @copyright 1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 1994-1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +/** +* This bit here is not qualified as file comment +* +* as it is not the first comment in the file +* +*/ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc new file mode 100644 index 000000000..520d34975 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc @@ -0,0 +1,11 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +echo 'hi'; \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js new file mode 100644 index 000000000..4bb4d50d6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js @@ -0,0 +1,10 @@ +/** + * File comment. + * + * @package Package + * @subpackage Subpackage + * @author Squiz Pty Ltd + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +print 'hi'; \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc new file mode 100644 index 000000000..b47603f20 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc @@ -0,0 +1,9 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc new file mode 100644 index 000000000..2fdeeba1f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc @@ -0,0 +1,3 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +class Foo { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc new file mode 100644 index 000000000..7074dac23 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ +#[Attribute] +class Foo { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc new file mode 100644 index 000000000..5ef90f2ad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc @@ -0,0 +1,9 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc new file mode 100644 index 000000000..f6c9d9968 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +enum Foo { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php new file mode 100644 index 000000000..ee81369ab --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FileCommentUnitTest.inc') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + case 'FileCommentUnitTest.1.js': + return [ + 1 => 1, + 22 => 2, + 23 => 1, + 24 => 2, + 25 => 2, + 26 => 1, + 27 => 2, + 28 => 2, + 32 => 2, + ]; + + case 'FileCommentUnitTest.4.inc': + case 'FileCommentUnitTest.6.inc': + case 'FileCommentUnitTest.7.inc': + case 'FileCommentUnitTest.9.inc': + return [1 => 1]; + + case 'FileCommentUnitTest.5.inc': + return [2 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc new file mode 100644 index 000000000..7e94bb265 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc @@ -0,0 +1,511 @@ +callSomeFunction(); + + }//end okFunction() + + + /** + * Comment inside function. + * + * @throws Exception + */ + function okFunction() + { + /** + * @var FooClass + */ + $foo = FooFactory::factory(); + throw new Exception; + + }//end okFunction + + /** + * Needs at throws tag for rethrown exception, + * even though we have one throws tag. + * + * @throws PHP_Exception1 + */ + public function notOkVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end notOkVariableRethrown() + + /** + * Needs at throws tag for rethrown exception, + * even though we have one throws tag. + * + * @throws PHP_Exception1 + */ + public function notOkVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception1 | PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end notOkVariableRethrown() + + /** + * Has correct throws tags for all exceptions + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function okVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end okVariableRethrown() + + /** + * Has correct throws tags for all exceptions + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function okVariableMultiRethrown() + { + try { + // Do something. + } catch (PHP_Exception1 | PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end okVariableMultiRethrown() +}//end class + +class NamespacedException { + /** + * @throws \Exception + */ + public function foo() { + throw new \Exception(); + } + + /** + * @throws \Foo\Bar\FooBarException + */ + public function fooBar2() { + throw new \Foo\Bar\FooBarException(); + } + + /** + * @throws FooBarException + */ + public function fooBar2() { + throw new \Foo\Bar\FooBarException(); + } +} + +class Foo { + /** + * Comment + */ + public function foo() { + }//end foo() + + public function bar() { + throw new Exception(); + } + + /** + * Returns information for a test. + * + * This info includes parameters, their valid values. + * + * @param integer $projectid Id of the project. + * + * @return array + * @throws ChannelException If the project is invalid. + */ + public static function getTestInfo($projectid=NULL) + { + try { + DAL::beginTransaction(); + DAL::commit(); + } catch (DALException $e) { + DAL::rollBack(); + throw new ChannelException($e); + } + } +} + +class Test +{ + /** + * Folder name. + * + * @var string + */ + protected $folderName; + + protected function setUp() + { + parent::setUp(); + + if ( !strlen($this->folderName) ) { + throw new \RuntimeException('The $this->folderName must be specified before proceeding.'); + } + } + + /* + * + */ + protected function foo() + { + } + + /** + * @return Closure + */ + public function getStuff() + { + return function () { + throw new RuntimeException("bam!"); + }; + } +} + +/** + * Class comment. + */ +class A +{ + /** + * Function B. + */ + public function b() + { + return new class { + public function c() + { + throw new \Exception(); + } + } + } +} + +/** + * Class comment. + */ +class A +{ + /** + * Function B. + */ + public function b() + { + return new class { + /** + * Tag and token number mismatch. + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function oneLessThrowsTagNeeded() + { + throw new PHP_Exception1('Error'); + + }//end oneLessThrowsTagNeeded() + } + } +} + +abstract class SomeClass { + /** + * Comment here. + */ + abstract public function getGroups(); +} + +class SomeClass { + /** + * Validates something. + * + * @param string $method The set method parameter. + * + * @return string The validated method. + * + * @throws Prefix_Invalid_Argument_Exception The invalid argument exception. + * @throws InvalidArgumentException The invalid argument exception. + */ + protected function validate_something( $something ) { + if ( ! Prefix_Validator::is_string( $something ) ) { + throw Prefix_Invalid_Argument_Exception::invalid_string_parameter( $something, 'something' ); + } + + if ( ! in_array( $something, $this->valid_http_something, true ) ) { + throw new InvalidArgumentException( sprintf( '%s is not a valid HTTP something', $something ) ); + } + + return $something; + } + + /** + * Comment + * + * @throws Exception1 Comment. + * @throws Exception2 Comment. + * @throws Exception3 Comment. + */ + public function foo() { + switch ($foo) { + case 1: + throw Exception1::a(); + case 2: + throw Exception1::b(); + case 3: + throw Exception1::c(); + case 4: + throw Exception2::a(); + case 5: + throw Exception2::b(); + default: + throw new Exception3; + + } + } +} + +namespace Test\Admin { + class NameSpacedClass { + /** + * @throws \ExceptionFromGlobalNamespace + */ + public function ExceptionInGlobalNamespace() { + throw new \ExceptionFromGlobalNamespace(); + } + + /** + * @throws ExceptionFromSameNamespace + */ + public function ExceptionInSameNamespace() { + throw new ExceptionFromSameNamespace(); + } + + /** + * @throws \Test\Admin\ExceptionFromSameNamespace + */ + public function ExceptionInSameNamespaceToo() { + throw new ExceptionFromSameNamespace(); + } + + /** + * @throws \Different\NameSpaceName\ExceptionFromDifferentNamespace + */ + public function ExceptionInSameNamespaceToo() { + throw new \Different\NameSpaceName\ExceptionFromDifferentNamespace(); + } + } +} + +namespace { + class GlobalNameSpaceClass { + /** + * @throws SomeGlobalException + */ + public function ThrowGlobalException() { + throw new SomeGlobalException(); + } + + /** + * @throws \SomeGlobalException + */ + public function ThrowGlobalExceptionToo() { + throw new SomeGlobalException(); + } + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php new file mode 100644 index 000000000..1e2d07faf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentThrowTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 21 => 1, + 35 => 1, + 47 => 1, + 61 => 2, + 106 => 1, + 123 => 1, + 200 => 1, + 219 => 1, + 287 => 1, + 397 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 000000000..4f59f60b7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,1048 @@ +MyClass) + */ +public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7) +{ + +}//end caseSensitive() + + +/** + * More type hint check for custom type and array. + * + * @param array $a1 Comment here. + * @param array $a2 Comment here. + * @param MyClass $a3 Comment here. + * @param MyClass $a4 Comment here. + * + * @return array(int => MyClass) + */ +public function typeHint(MyClass $a1, $a2, myclass $a3, $a4) +{ + return (3 => 'myclass obj'); + +}//end typeHint() + + +/** + * Mixed variable type separated by a '|'. + * + * @param array|string $a1 Comment here. + * @param mixed $a2 Comment here. + * @param string|array $a3 Comment here. + * @param MyClass|int $a4 Comment here. + * + * @return bool + */ +public function mixedType($a1, $a2, $a3, $a4) +{ + return true; + +}//end mixedType() + + +/** + * Array type. + * + * @param array(MyClass) $a1 OK. + * @param array() $a2 Invalid type. + * @param array( $a3 Typo. + * @param array(int) $a4 Use 'array(integer)' instead. + * @param array(int => integer) $a5 Use 'array(integer => integer)' instead. + * @param array(integer => bool) $a6 Use 'array(integer => boolean)' instead. + * @param aRRay $a7 Use 'array' instead. + * @param string $a8 String with unknown type hint. + * + * @return int + */ +public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8) +{ + return 1; + +}//end mixedArrayType() + + +/** + */ +function empty1() +{ +}//end empty1() + + +/** + * + */ +function empty2() +{ +}//end empty2() + + +/** + * + * + * + */ +function empty3() +{ +}//end empty3 + + +/** + * @return boolean + */ +public function missingShortDescriptionInFunctionComment() +{ + return true; + +}//end missingShortDescriptionInFunctionComment() + + +class Another_Class +{ + + /** + * Destructor should not include a return tag. + * + * @return void + */ + function __destruct() + { + return; + } + + /** + * Constructor should not include a return tag. + * + * @return void + */ + function __construct() + { + return; + } + +}//end class + + +/** + * Comment param alignment test. + * + * @param string $varrr1 Comment1.. + * @param string $vr2 Comment2. + * @param string $var3 Comment3.. + * + * @return void + */ +public static function paramAlign($varrr1, $vr2, $var3) +{ + +}//end paramAlign() + + +/** + * Comment. + * + * @param string $id Comment. + * @param array $design Comment. + * + * @return void + */ +public static function paint($id, array $design) +{ + +}//end paint() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @since 4.0.0 + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + return; + } + + return 'blah'; + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + + return 'blah'; + +}//end myFunction() + +/** + * Test function. + * + * @param string $arg1 An argument + * + * @access public + * @return bool + */ + +echo $blah; + +function myFunction($arg1) {} + +class MyClass() { + /** + * An abstract function. + * + * @return string[] + */ + abstract final protected function myFunction(); +} + +/** + * Comment. + * + * @param mixed $test An argument. + * + * @return mixed + */ +function test($test) +{ + if ($test === TRUE) { + return; + } + + return $test; + +}//end test() + + +/** Comment. + * + * @return mixed + * + */ +function test() +{ + +}//end test() + +/** + * Comment. + * + * @param \other\ns\item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\ns\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +// Closures should be ignored. +preg_replace_callback( + '~-([a-z])~', + function ($match) { + return strtoupper($match[1]); + }, + 'hello-world' +); + +$callback = function ($bar) use ($foo) + { + $bar += $foo; + }; + +/** + * Comment should end with '*', not '**' before the slash. + **/ +function test123() { + +} + +/** + * Cant use resource for type hint. + * + * @param resource $test An argument. + * + * @return mixed + */ +function test($test) +{ + return $test; + +}//end test() + +/** + * Variable number of args. + * + * @param string $a1 Comment here. + * @param string $a2 Comment here. + * @param string $a2,... Comment here. + * + * @return boolean + */ +public function variableArgs($a1, $a2) +{ + return true; + +}//end variableArgs() + +/** + * Contains closure. + * + * @return void + */ +public function containsClosure() +{ + function ($e) { + return new Event($e); + }, + +}//end containsClosure() + +/** + * 这是一条测试评论. + * + * @return void + */ +public function test() +{ + +}//end variableArgs() + +/** + * Uses callable. + * + * @param callable $cb Test parameter. + * + * @return void + */ +public function usesCallable(callable $cb) { + $cb(); +}//end usesCallable() + +/** + * Creates a map of tokens => line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character + * to use for splitting strings. + * + * @return void + * @throws Exception If something really bad + * happens while doing foo. + */ +public function foo(array &$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Some description. + * + * @param \Vendor\Package\SomeClass $someclass Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass2 Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass3 Some class. + * + * @return void + */ +public function foo(SomeClass $someclass, \OtherVendor\Package\SomeClass2 $someclass2, SomeClass3 $someclass3) +{ +} + +/** + * Gettext. + * + * @return string + */ +public function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Test + * + * @return void + * @throws E + */ +function myFunction() {} + +/** + * Yield test + * + * @return integer + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Yield test + * + * @return void + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Using "array" as a type hint should satisfy a specified array parameter type. + * + * @param MyClass[] $values An array of MyClass objects. + * + * @return void + */ +public function specifiedArray(array $values) { + +}// end specifiedArray() + +/** + * Using "callable" as a type hint should satisfy a "callback" parameter type. + * + * @param callback $cb A callback. + * + * @return void + */ +public function callableCallback(callable $cb) { + +}// end callableCallback() + +/** + * PHP7 type hints. + * + * @param string $name1 Comment. + * @param integer $name2 Comment. + * @param float $name3 Comment. + * @param boolean $name4 Comment. + * + * @return void + */ +public function myFunction (string $name1, int $name2, float $name3, bool $name4) { +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + +/** + * Return description function + correct type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + incorrect type. + * + * @return int This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + no return. + * + * @return void This is a description. + */ +public function myFunction() { +} + +/** + * Return description function + mixed return. + * + * @return mixed This is a description. + */ +public function myFunction() { +} + +/** + * Function comment. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Do something. + * + * @return void + */ +public function someFunc(): void +{ + $class = new class + { + /** + * Do something. + * + * @return string + */ + public function getString(): string + { + return 'some string'; + } + }; +} + +/** + * Return description function + mixed return types. + * + * @return bool|int This is a description. + */ +function returnTypeWithDescriptionA() +{ + return 5; + +}//end returnTypeWithDescriptionA() + + +/** + * Return description function + mixed return types. + * + * @return real|bool This is a description. + */ +function returnTypeWithDescriptionB() +{ + return 5; + +}//end returnTypeWithDescriptionB() + + +/** + * Return description function + lots of different mixed return types. + * + * @return int|object|string[]|real|double|float|bool|array(int=>MyClass)|callable And here we have a description + */ +function returnTypeWithDescriptionC() +{ + return 5; + +}//end returnTypeWithDescriptionC() + + +/** + * Return description function + lots of different mixed return types. + * + * @return array(int=>bool)|\OtherVendor\Package\SomeClass2|MyClass[]|void And here we have a description + */ +function returnTypeWithDescriptionD() +{ + +}//end returnTypeWithDescriptionD() + +/** + * Yield from test + * + * @return int[] + */ +function yieldFromTest() +{ + yield from foo(); +} + +/** + * Audio + * + * Generates an audio element to embed sounds + * + * @param mixed $src Either a source string or + * an array of sources. + * @param mixed $unsupportedMessage The message to display + * if the media tag is not supported by the browser. + * @param mixed $attributes HTML attributes. + * @return string + */ +function audio( + $src, + $unsupportedMessage = '', + $attributes = '', +) +{ + return 'test'; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithClosure() +{ + function () { + return; + }; + + return []; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithAnonymousClass() +{ + new class { + /** + * @return void + */ + public function test() { + return; + } + }; + + return []; +} + +/** + * @return void + */ +function returnVoidWithClosure() +{ + function () { + return 1; + }; +} + +/** + * @return void + */ +function returnVoidWithAnonymousClass() +{ + new class { + /** + * @return integer + */ + public function test() + { + return 1; + } + }; +} + +class TestReturnVoid +{ + /** + * @return void + */ + public function test() + { + function () { + return 4; + }; + } +} + +/** + * Comment here. + * + * @param integer $a This is A. + * @param ?array $b This is B. + * + * @return void + */ +public static function foo(?int $a, ?array $b) {} + +/** + * Comment here. + * + * @param object $a This is A. + * @param object $b This is B. + * + * @return void + */ +public function foo(object $a, ?object $b) {} + +/** + * Prepares given PHP class method for later code building. + * + * @param integer $foo Comment. + * - Additional comment. + * + * @return void + */ +function foo($foo) {} + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +// phpcs:set Squiz.Commenting.FunctionComment skipIfInheritdoc true + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +/** + * Foo. + * + * @param mixed $a Comment. + * + * @return mixed + */ +public function foo(mixed $a): mixed {} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] __construct,__destruct + +/** + * @return void + * @throws Exception If any other error occurs. */ +function throwCommentOneLine() {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed new file mode 100644 index 000000000..21a4103eb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed @@ -0,0 +1,1048 @@ + MyClass) + */ +public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7) +{ + +}//end caseSensitive() + + +/** + * More type hint check for custom type and array. + * + * @param array $a1 Comment here. + * @param array $a2 Comment here. + * @param MyClass $a3 Comment here. + * @param MyClass $a4 Comment here. + * + * @return array(integer => MyClass) + */ +public function typeHint(MyClass $a1, $a2, myclass $a3, $a4) +{ + return (3 => 'myclass obj'); + +}//end typeHint() + + +/** + * Mixed variable type separated by a '|'. + * + * @param array|string $a1 Comment here. + * @param mixed $a2 Comment here. + * @param string|array $a3 Comment here. + * @param MyClass|integer $a4 Comment here. + * + * @return boolean + */ +public function mixedType($a1, $a2, $a3, $a4) +{ + return true; + +}//end mixedType() + + +/** + * Array type. + * + * @param array(MyClass) $a1 OK. + * @param array $a2 Invalid type. + * @param array $a3 Typo. + * @param array(integer) $a4 Use 'array(integer)' instead. + * @param array(integer => integer) $a5 Use 'array(integer => integer)' instead. + * @param array(integer => boolean) $a6 Use 'array(integer => boolean)' instead. + * @param array $a7 Use 'array' instead. + * @param string $a8 String with unknown type hint. + * + * @return integer + */ +public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8) +{ + return 1; + +}//end mixedArrayType() + + +/** + */ +function empty1() +{ +}//end empty1() + + +/** + * + */ +function empty2() +{ +}//end empty2() + + +/** + * + * + * + */ +function empty3() +{ +}//end empty3 + + +/** + * @return boolean + */ +public function missingShortDescriptionInFunctionComment() +{ + return true; + +}//end missingShortDescriptionInFunctionComment() + + +class Another_Class +{ + + /** + * Destructor should not include a return tag. + * + * @return void + */ + function __destruct() + { + return; + } + + /** + * Constructor should not include a return tag. + * + * @return void + */ + function __construct() + { + return; + } + +}//end class + + +/** + * Comment param alignment test. + * + * @param string $varrr1 Comment1.. + * @param string $vr2 Comment2. + * @param string $var3 Comment3.. + * + * @return void + */ +public static function paramAlign($varrr1, $vr2, $var3) +{ + +}//end paramAlign() + + +/** + * Comment. + * + * @param string $id Comment. + * @param array $design Comment. + * + * @return void + */ +public static function paint($id, array $design) +{ + +}//end paint() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @since 4.0.0 + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + return; + } + + return 'blah'; + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + + return 'blah'; + +}//end myFunction() + +/** + * Test function. + * + * @param string $arg1 An argument + * + * @access public + * @return bool + */ + +echo $blah; + +function myFunction($arg1) {} + +class MyClass() { + /** + * An abstract function. + * + * @return string[] + */ + abstract final protected function myFunction(); +} + +/** + * Comment. + * + * @param mixed $test An argument. + * + * @return mixed + */ +function test($test) +{ + if ($test === TRUE) { + return; + } + + return $test; + +}//end test() + + +/** Comment. + * + * @return mixed + * + */ +function test() +{ + +}//end test() + +/** + * Comment. + * + * @param \other\ns\item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\ns\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +// Closures should be ignored. +preg_replace_callback( + '~-([a-z])~', + function ($match) { + return strtoupper($match[1]); + }, + 'hello-world' +); + +$callback = function ($bar) use ($foo) + { + $bar += $foo; + }; + +/** + * Comment should end with '*', not '**' before the slash. + **/ +function test123() { + +} + +/** + * Cant use resource for type hint. + * + * @param resource $test An argument. + * + * @return mixed + */ +function test($test) +{ + return $test; + +}//end test() + +/** + * Variable number of args. + * + * @param string $a1 Comment here. + * @param string $a2 Comment here. + * @param string $a2,... Comment here. + * + * @return boolean + */ +public function variableArgs($a1, $a2) +{ + return true; + +}//end variableArgs() + +/** + * Contains closure. + * + * @return void + */ +public function containsClosure() +{ + function ($e) { + return new Event($e); + }, + +}//end containsClosure() + +/** + * 这是一条测试评论. + * + * @return void + */ +public function test() +{ + +}//end variableArgs() + +/** + * Uses callable. + * + * @param callable $cb Test parameter. + * + * @return void + */ +public function usesCallable(callable $cb) { + $cb(); +}//end usesCallable() + +/** + * Creates a map of tokens => line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character + * to use for splitting strings. + * + * @return void + * @throws Exception If something really bad + * happens while doing foo. + */ +public function foo(array &$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Some description. + * + * @param \Vendor\Package\SomeClass $someclass Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass2 Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass3 Some class. + * + * @return void + */ +public function foo(SomeClass $someclass, \OtherVendor\Package\SomeClass2 $someclass2, SomeClass3 $someclass3) +{ +} + +/** + * Gettext. + * + * @return string + */ +public function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Test + * + * @return void + * @throws E + */ +function myFunction() {} + +/** + * Yield test + * + * @return integer + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Yield test + * + * @return void + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Using "array" as a type hint should satisfy a specified array parameter type. + * + * @param MyClass[] $values An array of MyClass objects. + * + * @return void + */ +public function specifiedArray(array $values) { + +}// end specifiedArray() + +/** + * Using "callable" as a type hint should satisfy a "callback" parameter type. + * + * @param callback $cb A callback. + * + * @return void + */ +public function callableCallback(callable $cb) { + +}// end callableCallback() + +/** + * PHP7 type hints. + * + * @param string $name1 Comment. + * @param integer $name2 Comment. + * @param float $name3 Comment. + * @param boolean $name4 Comment. + * + * @return void + */ +public function myFunction (string $name1, int $name2, float $name3, bool $name4) { +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + +/** + * Return description function + correct type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + incorrect type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + no return. + * + * @return void This is a description. + */ +public function myFunction() { +} + +/** + * Return description function + mixed return. + * + * @return mixed This is a description. + */ +public function myFunction() { +} + +/** + * Function comment. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Do something. + * + * @return void + */ +public function someFunc(): void +{ + $class = new class + { + /** + * Do something. + * + * @return string + */ + public function getString(): string + { + return 'some string'; + } + }; +} + +/** + * Return description function + mixed return types. + * + * @return boolean|integer This is a description. + */ +function returnTypeWithDescriptionA() +{ + return 5; + +}//end returnTypeWithDescriptionA() + + +/** + * Return description function + mixed return types. + * + * @return float|boolean This is a description. + */ +function returnTypeWithDescriptionB() +{ + return 5; + +}//end returnTypeWithDescriptionB() + + +/** + * Return description function + lots of different mixed return types. + * + * @return integer|object|string[]|float|boolean|array(integer => MyClass)|callable And here we have a description + */ +function returnTypeWithDescriptionC() +{ + return 5; + +}//end returnTypeWithDescriptionC() + + +/** + * Return description function + lots of different mixed return types. + * + * @return array(integer => boolean)|\OtherVendor\Package\SomeClass2|MyClass[]|void And here we have a description + */ +function returnTypeWithDescriptionD() +{ + +}//end returnTypeWithDescriptionD() + +/** + * Yield from test + * + * @return int[] + */ +function yieldFromTest() +{ + yield from foo(); +} + +/** + * Audio + * + * Generates an audio element to embed sounds + * + * @param mixed $src Either a source string or + * an array of sources. + * @param mixed $unsupportedMessage The message to display + * if the media tag is not supported by the browser. + * @param mixed $attributes HTML attributes. + * @return string + */ +function audio( + $src, + $unsupportedMessage = '', + $attributes = '', +) +{ + return 'test'; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithClosure() +{ + function () { + return; + }; + + return []; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithAnonymousClass() +{ + new class { + /** + * @return void + */ + public function test() { + return; + } + }; + + return []; +} + +/** + * @return void + */ +function returnVoidWithClosure() +{ + function () { + return 1; + }; +} + +/** + * @return void + */ +function returnVoidWithAnonymousClass() +{ + new class { + /** + * @return integer + */ + public function test() + { + return 1; + } + }; +} + +class TestReturnVoid +{ + /** + * @return void + */ + public function test() + { + function () { + return 4; + }; + } +} + +/** + * Comment here. + * + * @param integer $a This is A. + * @param array $b This is B. + * + * @return void + */ +public static function foo(?int $a, ?array $b) {} + +/** + * Comment here. + * + * @param object $a This is A. + * @param object $b This is B. + * + * @return void + */ +public function foo(object $a, ?object $b) {} + +/** + * Prepares given PHP class method for later code building. + * + * @param integer $foo Comment. + * - Additional comment. + * + * @return void + */ +function foo($foo) {} + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +// phpcs:set Squiz.Commenting.FunctionComment skipIfInheritdoc true + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +/** + * Foo. + * + * @param mixed $a Comment. + * + * @return mixed + */ +public function foo(mixed $a): mixed {} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] __construct,__destruct + +/** + * @return void + * @throws Exception If any other error occurs. */ +function throwCommentOneLine() {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 000000000..632b7c51b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,177 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 5 => 1, + 10 => 3, + 12 => 2, + 13 => 2, + 14 => 1, + 15 => 1, + 28 => 1, + 43 => 1, + 76 => 1, + 87 => 1, + 103 => 1, + 109 => 1, + 112 => 1, + 122 => 1, + 123 => 3, + 124 => 2, + 125 => 1, + 126 => 1, + 137 => 4, + 138 => 4, + 139 => 4, + 143 => 2, + 152 => 1, + 155 => 2, + 159 => 1, + 166 => 1, + 173 => 1, + 183 => 1, + 190 => 2, + 193 => 2, + 196 => 1, + 199 => 2, + 210 => 1, + 211 => 1, + 222 => 1, + 223 => 1, + 224 => 1, + 225 => 1, + 226 => 1, + 227 => 1, + 230 => 2, + 232 => 2, + 246 => 1, + 248 => 4, + 261 => 1, + 263 => 1, + 276 => 1, + 277 => 1, + 278 => 1, + 279 => 1, + 280 => 1, + 281 => 1, + 284 => 1, + 286 => 7, + 294 => 1, + 302 => 1, + 312 => 1, + 358 => 1, + 359 => 2, + 372 => 1, + 373 => 1, + 387 => 1, + 407 => 1, + 441 => 1, + 500 => 1, + 526 => 1, + 548 => 1, + 641 => 1, + 669 => 1, + 688 => 1, + 744 => 1, + 748 => 1, + 767 => 1, + 789 => 1, + 792 => 1, + 794 => 1, + 797 => 1, + 801 => 1, + 828 => 1, + 840 => 1, + 852 => 1, + 864 => 1, + 886 => 1, + 888 => 1, + 890 => 1, + 978 => 1, + 997 => 1, + 1004 => 2, + 1006 => 1, + 1029 => 1, + ]; + + // Scalar type hints only work from PHP 7 onwards. + if (PHP_VERSION_ID >= 70000) { + $errors[17] = 3; + $errors[128] = 1; + $errors[143] = 3; + $errors[161] = 2; + $errors[201] = 1; + $errors[232] = 7; + $errors[363] = 3; + $errors[377] = 1; + $errors[575] = 2; + $errors[627] = 1; + $errors[1002] = 1; + } else { + $errors[729] = 4; + $errors[740] = 2; + $errors[752] = 2; + $errors[982] = 1; + } + + // Object type hints only work from PHP 7.2 onwards. + if (PHP_VERSION_ID >= 70200) { + $errors[627] = 2; + } else { + $errors[992] = 2; + } + + // Mixed type hints only work from PHP 8.0 onwards. + if (PHP_VERSION_ID >= 80000) { + $errors[265] = 1; + $errors[459] = 1; + $errors[893] = 3; + } else { + $errors[1023] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc new file mode 100644 index 000000000..10a0b4b4c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc @@ -0,0 +1,183 @@ + One +// -> One.One +// -> Two + +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + +/** + * Comment should be ignored in PHP 5.4. + * + */ +trait MyTrait { + +} + +$foo = 'foo'; // Var set to foo. + +echo $foo; + +// Comment here. +echo $foo; + +/** + * Comments about the include + */ +include_once($blah); + +// some comment without capital or full stop +echo $foo; // An unrelated comment. + +// An unrelated comment. +echo $foo; // some comment without capital or full stop + +class Foo +{ + // This is fine. + + /** + * Spacing is ignored above. + */ + function bar(){} +} + +if ($foo) { +}//end if +// Another comment here. +$foo++; + +if ($foo) { +}//end if +// another comment here. +$foo++; + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} + +/** + * Comment should be ignored. + * + */ +enum MyEnum { + +} + +/* + * N.B.: The below test line must be the last test in the file. + * Testing that a new line after an inline comment when it's the last non-whitespace + * token in a file, does *not* throw an error as this would conflict with the common + * "new line required at end of file" rule. + */ + +// For this test line having an empty line below it, is fine. diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed new file mode 100644 index 000000000..97ae01490 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed @@ -0,0 +1,176 @@ + One +// -> One.One +// -> Two +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + +/** + * Comment should be ignored in PHP 5.4. + * + */ +trait MyTrait { + +} + +$foo = 'foo'; // Var set to foo. + +echo $foo; + +// Comment here. +echo $foo; + +/** + * Comments about the include + */ +include_once($blah); + +// some comment without capital or full stop +echo $foo; // An unrelated comment. + +// An unrelated comment. +echo $foo; // some comment without capital or full stop + +class Foo +{ + // This is fine. + + /** + * Spacing is ignored above. + */ + function bar(){} +} + +if ($foo) { +}//end if +// Another comment here. +$foo++; + +if ($foo) { +}//end if +// another comment here. +$foo++; + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} + +/** + * Comment should be ignored. + * + */ +enum MyEnum { + +} + +/* + * N.B.: The below test line must be the last test in the file. + * Testing that a new line after an inline comment when it's the last non-whitespace + * token in a file, does *not* throw an error as this would conflict with the common + * "new line required at end of file" rule. + */ + +// For this test line having an empty line below it, is fine. diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js new file mode 100644 index 000000000..6b1093e6a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js @@ -0,0 +1,129 @@ +// Some content here. +var code = 'hello'; + +// This comment contains # multiple +// hash signs (#). +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +function testFunction() +{ + // Callback methods which are added by external objects. + this.callbacks = {}; + +}//end testFunction() + +/** + * This is the first line of a class comment. + * This is the second line. + */ +myClass.prototype = { + + /** + * This is the first line of a method comment. + * This is the second line. + */ + load: function(url, callback) + { + // Some code here. + + } +}; + +// some code goes here! + +/* + A longer comment goes here. + It spans multiple lines!! + Or does it? +*/ + +// 0This is a simple multi-line +// comment! +code = 'hello'; + +//This is not valid. +code = 'hello'; + +// Neither is this! +code = 'hello'; + +// +code = 'hello'; + +/** Neither is this! **/ +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +var myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myClass.myFunction = function() { +} + +dfx.getIframeDocument = function(iframe) +{ + return doc; + +};//end dfx.getIframeDocument() + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +// Here is some inline example code: +// -> One +// -> One.One +// -> Two + +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + + +var foo = 'foo'; // Var set to foo. + +console.info(foo); + +// Comment here. +console.info(foo); + +//** +* invalid comment +*/ + +// some comment without capital or full stop +console.log(foo); // An unrelated comment. + +// An unrelated comment. +console.log(foo); // some comment without capital or full stop diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed new file mode 100644 index 000000000..20e5041e6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed @@ -0,0 +1,125 @@ +// Some content here. +var code = 'hello'; + +// This comment contains # multiple +// hash signs (#). +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +function testFunction() +{ + // Callback methods which are added by external objects. + this.callbacks = {}; + +}//end testFunction() + +/** + * This is the first line of a class comment. + * This is the second line. + */ +myClass.prototype = { + + /** + * This is the first line of a method comment. + * This is the second line. + */ + load: function(url, callback) + { + // Some code here. + } +}; + +// some code goes here! +/* + A longer comment goes here. + It spans multiple lines!! + Or does it? +*/ + +// 0This is a simple multi-line +// comment! +code = 'hello'; + +// This is not valid. +code = 'hello'; + +// Neither is this! +code = 'hello'; + +code = 'hello'; + +/** Neither is this! **/ +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +var myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myClass.myFunction = function() { +} + +dfx.getIframeDocument = function(iframe) +{ + return doc; + +};//end dfx.getIframeDocument() + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +// Here is some inline example code: +// -> One +// -> One.One +// -> Two +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + + +var foo = 'foo'; // Var set to foo. + +console.info(foo); + +// Comment here. +console.info(foo); + +// ** +* invalid comment +*/ + +// some comment without capital or full stop +console.log(foo); // An unrelated comment. + +// An unrelated comment. +console.log(foo); // some comment without capital or full stop diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php new file mode 100644 index 000000000..e4a5298bf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InlineCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='InlineCommentUnitTest.inc') + { + switch ($testFile) { + case 'InlineCommentUnitTest.inc': + $errors = [ + 17 => 1, + 27 => 1, + 28 => 1, + 32 => 2, + 36 => 1, + 44 => 2, + 58 => 1, + 61 => 1, + 64 => 1, + 67 => 1, + 95 => 1, + 96 => 1, + 97 => 3, + 118 => 1, + 126 => 2, + 130 => 2, + 149 => 1, + ]; + + return $errors; + case 'InlineCommentUnitTest.js': + return [ + 31 => 1, + 36 => 2, + 48 => 1, + 51 => 1, + 54 => 1, + 57 => 1, + 102 => 1, + 103 => 1, + 104 => 3, + 118 => 1, + 121 => 1, + 125 => 2, + 129 => 2, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc new file mode 100644 index 000000000..d6c4cf6c8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc @@ -0,0 +1,1033 @@ + match ($foo) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 + }, +]; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed new file mode 100644 index 000000000..176cfe248 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed @@ -0,0 +1,1033 @@ + match ($foo) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 + },//end match +]; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js new file mode 100644 index 000000000..c0cf2821d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js @@ -0,0 +1,444 @@ +function long_function() +{ + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + } +} + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + for (val =1; val < 20; val++) { + // Short for. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + while (something) { + // Short while. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} //end if + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} else { + // Short ELSE +} //end if + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +if (true) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else if (condition) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +if (something) { + // Line 1 + // Line 2 +} else if (somethingElse) { + // Line 1 + // Line 2 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +switch (something) { + case '1': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '2': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '3': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '4': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '5': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; +} + +// Wrong comment +if (condition) { + condition = true; +}//end foreach diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed new file mode 100644 index 000000000..231b51c5c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed @@ -0,0 +1,444 @@ +function long_function() +{ + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if +} + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + for (val =1; val < 20; val++) { + // Short for. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + while (something) { + // Short while. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} //end if + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} else { + // Short ELSE +} //end if + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +if (true) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else if (condition) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +if (something) { + // Line 1 + // Line 2 +} else if (somethingElse) { + // Line 1 + // Line 2 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +switch (something) { + case '1': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '2': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '3': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '4': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '5': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; +}//end switch + +// Wrong comment +if (condition) { + condition = true; +}//end if diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php new file mode 100644 index 000000000..5b61612c5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LongConditionClosingCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='LongConditionClosingCommentUnitTest.inc') + { + switch ($testFile) { + case 'LongConditionClosingCommentUnitTest.inc': + return [ + 49 => 1, + 99 => 1, + 146 => 1, + 192 => 1, + 215 => 1, + 238 => 1, + 261 => 1, + 286 => 1, + 309 => 1, + 332 => 1, + 355 => 1, + 378 => 1, + 493 => 1, + 531 => 1, + 536 => 1, + 540 => 1, + 562 => 1, + 601 => 1, + 629 => 1, + 663 => 1, + 765 => 1, + 798 => 1, + 811 => 1, + 897 => 1, + 931 => 1, + 962 => 1, + 985 => 2, + 1008 => 1, + 1032 => 1, + ]; + break; + case 'LongConditionClosingCommentUnitTest.js': + return [ + 47 => 1, + 97 => 1, + 144 => 1, + 190 => 1, + 213 => 1, + 238 => 1, + 261 => 1, + 284 => 1, + 307 => 1, + 401 => 1, + 439 => 1, + 444 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js new file mode 100644 index 000000000..6de642107 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js @@ -0,0 +1,36 @@ +function test(id, buttons) // cool function +{ + alert('hello'); + alert('hello again'); // And again. + // Valid comment. + +}//end test() + +var good = true; // Indeed. + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +dfx.getIframeDocument = function(iframe) +{ + + return doc; + +};//end dfx.getIframeDocument() + +// Verify that multi-line control structure with comments and annotations are left alone. +if (condition // comment + && anotherCondition) { + condition = true; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed new file mode 100644 index 000000000..1953760da --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed @@ -0,0 +1,39 @@ +function test(id, buttons) +// cool function +{ + alert('hello'); + alert('hello again'); +// And again. + // Valid comment. + +}//end test() + +var good = true; +// Indeed. + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +dfx.getIframeDocument = function(iframe) +{ + + return doc; + +};//end dfx.getIframeDocument() + +// Verify that multi-line control structure with comments and annotations are left alone. +if (condition // comment + && anotherCondition) { + condition = true; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js new file mode 100644 index 000000000..88d0e7d44 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js @@ -0,0 +1,2 @@ +// Comment as first thing in a JS file. +var i = 100; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc new file mode 100644 index 000000000..b83469613 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc @@ -0,0 +1,54 @@ + function($b) { + }, // comment. + 'key' => 'value', // phpcs:ignore Standard.Category.SniffName -- for reasons. + 'key' => 'value', // comment. +]; + +// Verify that multi-line control structure with comments and annotations are left alone. +for ( + $i = 0; /* Start */ + $i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + $i++ // comment + +) {} + +if ( $condition === true // comment + && $anotherCondition === false +) {} + +$match = match($foo // comment + && $bar +) { + 1 => 1, // comment +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed new file mode 100644 index 000000000..21a4bbe03 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed @@ -0,0 +1,59 @@ + function($b) { + }, // comment. + 'key' => 'value', // phpcs:ignore Standard.Category.SniffName -- for reasons. + 'key' => 'value', +// comment. +]; + +// Verify that multi-line control structure with comments and annotations are left alone. +for ( + $i = 0; /* Start */ + $i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + $i++ // comment + +) {} + +if ( $condition === true // comment + && $anotherCondition === false +) {} + +$match = match($foo // comment + && $bar +) { + 1 => 1, +// comment +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php new file mode 100644 index 000000000..a04426f15 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class PostStatementCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='PostStatementCommentUnitTest.inc') + { + switch ($testFile) { + case 'PostStatementCommentUnitTest.inc': + return [ + 6 => 1, + 10 => 1, + 18 => 1, + 35 => 1, + 53 => 1, + ]; + + case 'PostStatementCommentUnitTest.1.js': + return [ + 1 => 1, + 4 => 1, + 9 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc new file mode 100644 index 000000000..36efc443b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc @@ -0,0 +1,404 @@ + $content) { + echo $content; + } + + return $var1; + + }//end checkVariable() + + + /** + * + * + */ + $emptyVarDoc = ''; + + /** + * Var type checking (int v.s. integer). + * + * @var int + */ + private $_varSimpleTypeCheck; + + + /** + * Var type checking (array(int => string) v.s. array(int => string)). + * + * @var array(int => string) + */ + private $_varArrayTypeCheck; + + + /** + * Boolean @var tag Capitalized + * + * @var Boolean + */ + public $CapBoolTag = true; + + + /** + * Boolean @var tag Capitalized + * + * @var BOOLEAN + */ + public $CapBoolTag2 = true; + + + /** + * Double @var tag Capitalized + * + * @var Double + */ + public $CapDoubleTag = 1; + + + /** + * Double @var tag Capitalized + * + * @var DOUBLE + */ + public $CapDoubleTag2 = 1; + + + /** + * Real @var tag Capitalized + * + * @var Real + */ + public $CapRealTag = 1; + + + /** + * Real @var tag Capitalized + * + * @var REAL + */ + public $CapRealTag2 = 1; + + + /** + * Float @var tag Capitalized + * + * @var Float + */ + public $CapFloatTag = 1; + + + /** + * Float @var tag Capitalized + * + * @var FLOAT + */ + public $CapFloatTag2 = 1; + + + /** + * Int @var tag Capitalized + * + * @var Int + */ + public $CapIntTag = 1; + + + /** + * Int @var tag Capitalized + * + * @var INT + */ + public $CapIntTag2 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var Integer + */ + public $CapIntTag3 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var INTEGER + */ + public $CapIntTag4 = 1; + + + /** + * Array @var tag Capitalized + * + * @var Array + */ + public $CapVarTag = []; + + + /** + * Array @var tag All Caps + * + * @var ARRAY + */ + public $CapVarTag2 = []; + + + /** + * Array @var tag Capitalized + * + * @var Array() + */ + public $CapVarTag3 = []; + + + /** + * Array @var tag All Caps + * + * @var ARRAY() + */ + public $CapVarTag4 = []; + + + /** + * Var type checking (STRING v.s. string). + * + * @var STRING + */ + private $_varCaseTypeCheck; + + + /** + * @var integer + */ + private $_varWithNoShortComment; + + protected $noComment2 = ''; + + + /** + * @var int Var type checking (int v.s. integer) with single-line comment. + */ + private $_varSimpleTypeCheckSingleLine; + + +}//end class + + +/** + * VariableCommentUnitTest2. + * + * Long description goes here. + * + */ +class VariableCommentUnitTest2 +{ + + public $hello; + + /** Comment starts here. + * + * @var string + * + */ + private $_varCaseTypeCheck; + + /** + * 这是一条测试评论. + * + * @var string + */ + public $foo; + +}//end class + + +/* + * Class comment + */ +class Foo +{ + + protected $bar; + + /** + * Short description of the member variable. + * + * @var array + */ + public static array $variableName = array(); + +} + +class Foo +{ + + /** + * Short description of the member variable. + * + * @var array + */ + public array $variableName = array(); + + + // Not "/**" style comment. + // + // @var string + private ?Folder\ClassName $_incorrectCommentStyle = null; + + + var int $noComment = 1; + } + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; +} + +class ReadOnlyProps +{ + /** + * Short description of the member variable. + * + * @var array + */ + public readonly array $variableName = array(); + + /** + * Short description of the member variable. + * + * @var + */ + readonly protected ?int $variableName = 10; + + private readonly string $variable; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed new file mode 100644 index 000000000..5c652f540 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed @@ -0,0 +1,404 @@ + $content) { + echo $content; + } + + return $var1; + + }//end checkVariable() + + + /** + * + * + */ + $emptyVarDoc = ''; + + /** + * Var type checking (int v.s. integer). + * + * @var integer + */ + private $_varSimpleTypeCheck; + + + /** + * Var type checking (array(int => string) v.s. array(int => string)). + * + * @var array(integer => string) + */ + private $_varArrayTypeCheck; + + + /** + * Boolean @var tag Capitalized + * + * @var boolean + */ + public $CapBoolTag = true; + + + /** + * Boolean @var tag Capitalized + * + * @var boolean + */ + public $CapBoolTag2 = true; + + + /** + * Double @var tag Capitalized + * + * @var float + */ + public $CapDoubleTag = 1; + + + /** + * Double @var tag Capitalized + * + * @var float + */ + public $CapDoubleTag2 = 1; + + + /** + * Real @var tag Capitalized + * + * @var float + */ + public $CapRealTag = 1; + + + /** + * Real @var tag Capitalized + * + * @var float + */ + public $CapRealTag2 = 1; + + + /** + * Float @var tag Capitalized + * + * @var float + */ + public $CapFloatTag = 1; + + + /** + * Float @var tag Capitalized + * + * @var float + */ + public $CapFloatTag2 = 1; + + + /** + * Int @var tag Capitalized + * + * @var integer + */ + public $CapIntTag = 1; + + + /** + * Int @var tag Capitalized + * + * @var integer + */ + public $CapIntTag2 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var integer + */ + public $CapIntTag3 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var integer + */ + public $CapIntTag4 = 1; + + + /** + * Array @var tag Capitalized + * + * @var array + */ + public $CapVarTag = []; + + + /** + * Array @var tag All Caps + * + * @var array + */ + public $CapVarTag2 = []; + + + /** + * Array @var tag Capitalized + * + * @var array + */ + public $CapVarTag3 = []; + + + /** + * Array @var tag All Caps + * + * @var array + */ + public $CapVarTag4 = []; + + + /** + * Var type checking (STRING v.s. string). + * + * @var string + */ + private $_varCaseTypeCheck; + + + /** + * @var integer + */ + private $_varWithNoShortComment; + + protected $noComment2 = ''; + + + /** + * @var integer Var type checking (int v.s. integer) with single-line comment. + */ + private $_varSimpleTypeCheckSingleLine; + + +}//end class + + +/** + * VariableCommentUnitTest2. + * + * Long description goes here. + * + */ +class VariableCommentUnitTest2 +{ + + public $hello; + + /** Comment starts here. + * + * @var string + * + */ + private $_varCaseTypeCheck; + + /** + * 这是一条测试评论. + * + * @var string + */ + public $foo; + +}//end class + + +/* + * Class comment + */ +class Foo +{ + + protected $bar; + + /** + * Short description of the member variable. + * + * @var array + */ + public static array $variableName = array(); + +} + +class Foo +{ + + /** + * Short description of the member variable. + * + * @var array + */ + public array $variableName = array(); + + + // Not "/**" style comment. + // + // @var string + private ?Folder\ClassName $_incorrectCommentStyle = null; + + + var int $noComment = 1; + } + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; +} + +class ReadOnlyProps +{ + /** + * Short description of the member variable. + * + * @var array + */ + public readonly array $variableName = array(); + + /** + * Short description of the member variable. + * + * @var + */ + readonly protected ?int $variableName = 10; + + private readonly string $variable; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php new file mode 100644 index 000000000..1af5e1484 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class VariableCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 21 => 1, + 24 => 1, + 56 => 1, + 64 => 1, + 73 => 1, + 84 => 1, + 130 => 1, + 136 => 1, + 144 => 1, + 152 => 1, + 160 => 1, + 168 => 1, + 176 => 1, + 184 => 1, + 192 => 1, + 200 => 1, + 208 => 1, + 216 => 1, + 224 => 1, + 232 => 1, + 240 => 1, + 248 => 1, + 256 => 1, + 264 => 1, + 272 => 1, + 280 => 1, + 290 => 1, + 294 => 1, + 311 => 1, + 336 => 1, + 361 => 1, + 364 => 1, + 399 => 1, + 403 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [93 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc new file mode 100644 index 000000000..8eaf1b037 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc @@ -0,0 +1,310 @@ + 0); + +do +{ + echo $i; +} while ($i > 0); + +do +{ + echo $i; +} +while ($i > 0); + +do { echo $i; } while ($i > 0); + +do{ + echo $i; +}while($i > 0); + +while ($i < 1) { + echo $i; +} + +while($i < 1){ + echo $i; +} + +while ($i < 1) { echo $i; } + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for($i = 1; $i < 1; $i++){ + echo $i; +} + +for ($i = 1; $i < 1; $i++) { echo $i; } + +if ($i == 0) { + $i = 1; +} + +if($i == 0){ + $i = 1; +} + +if ($i == 0) { $i = 1; } + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else if($i == 2){ + $i = 0; +} + +if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; } + +if ($i == 0) { // comments are allowed + $i = 1; +} + +if ($i == 0) {// comments are allowed + $i = 1; +} + +if ($i == 0) { /* comments are allowed*/ + $i = 1; +} + +if ($i == 0) +{ // this is ok + $i = 1; +} + +if ($i == 0) /* this is ok */ { +} + +try { + $code = 'this'; +} catch (Exception $e) { + // Caught! +} + +try { $code = 'this'; } catch (Exception $e) { + // Caught! +} + +do { echo $i; +} while ($i > 0); + +if ($i === 0) { + + $i = 1 +} + +if ($a) { + +} +elseif ($b) { +} + +foreach ($items as $item) { + echo $item; +} + +foreach($items as $item){ + echo $item; +} + +if ($a && $b) // && $c) +{ +} + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +try { + // try body +} +catch (FirstExceptionType $e) { + // catch body +} +catch (OtherExceptionType $e) { + // catch body +} + +switch($foo) { + + case 'bar': + break; + +} + +if ($foo) : +endif; + +?> + +getRow()): ?> +

    + + + +
    + +
    + + + + + + + hello + + + + hello + + + + +getRow()) : ?> +

    + + + + + + + + hello + + + + hello + + 1, +}; + +$r = match($x){1 => 1}; + +// Intentional parse error. This should be the last test in the file. +foreach + // Some unrelated comment. diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed new file mode 100644 index 000000000..dc5233d91 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.inc.fixed @@ -0,0 +1,314 @@ + 0); + +do { + echo $i; +} while ($i > 0); + +do { + echo $i; +} while ($i > 0); + +do { +echo $i; } while ($i > 0); + +do { + echo $i; +} while ($i > 0); + +while ($i < 1) { + echo $i; +} + +while ($i < 1) { + echo $i; +} + +while ($i < 1) { +echo $i; } + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for ($i = 1; $i < 1; $i++) { +echo $i; } + +if ($i == 0) { + $i = 1; +} + +if ($i == 0) { + $i = 1; +} + +if ($i == 0) { +$i = 1; } + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { +$i = 1; } else { +$i = 0; } + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { +$i = 1; } else if ($i == 2) { +$i = 0; } + +if ($i == 0) { // comments are allowed + $i = 1; +} + +if ($i == 0) {// comments are allowed + $i = 1; +} + +if ($i == 0) { /* comments are allowed*/ + $i = 1; +} + +if ($i == 0) { // this is ok + $i = 1; +} + +if ($i == 0) { /* this is ok */ +} + +try { + $code = 'this'; +} catch (Exception $e) { + // Caught! +} + +try { +$code = 'this'; } catch (Exception $e) { + // Caught! +} + +do { +echo $i; +} while ($i > 0); + +if ($i === 0) { + + $i = 1 +} + +if ($a) { + +} elseif ($b) { +} + +foreach ($items as $item) { + echo $item; +} + +foreach ($items as $item) { + echo $item; +} + +if ($a && $b) { // && $c) +} + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +try { + // try body +} catch (FirstExceptionType $e) { + // catch body +} catch (OtherExceptionType $e) { + // catch body +} + +switch ($foo) { + + case 'bar': + break; + +} + +if ($foo) : +endif; + +?> + +getRow()) : ?> +

    + + + +
    + +
    + + + + + + + hello + + + + hello + + + + +getRow()): ?> +

    + + + + + + + + hello + + + + hello + + 1, +}; + +$r = match ($x) { +1 => 1}; + +// Intentional parse error. This should be the last test in the file. +foreach + // Some unrelated comment. diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js new file mode 100644 index 000000000..6c2e9ffe0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js @@ -0,0 +1,135 @@ + +i = 0; +do { + i = 0; +} while (i > 0); + +do +{ + i = 0; +} while (i > 0); + +do +{ + i = 0; +} +while (i > 0); + +do { i = 0; } while (i > 0); + +do{ + i = 0; +}while(i > 0); + +while (i < 1) { + i = 0; +} + +while(i < 1){ + i = 0; +} + +while (i < 1) { i = 0; } + +for (i = 1; i < 1; i++) { + i = 0; +} + +for(i = 1; i < 1; i++){ + i = 0; +} + +for (i = 1; i < 1; i++) { i = 0; } + +if (i == 0) { + i = 1; +} + +if(i == 0){ + i = 1; +} + +if (i == 0) { i = 1; } + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { + i = 1; +}else{ + i = 0; +} + +if (i == 0) { i = 1; } else { i = 0; } + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { + i = 1; +}else if(i == 2){ + i = 0; +} + +if (i == 0) { i = 1; } else if (i == 2) { i = 0; } + +if (i == 0) { // comments are allowed + i = 1; +} + +if (i == 0) {// comments are allowed + i = 1; +} + +if (i == 0) { /* comments are allowed*/ + i = 1; +} + +if (i == 0) +{ // this is ok + i = 1; +} + +if (i == 0) /* this is ok */ { +} + +try { + code = 'this'; +} catch (e) { + // Caught! +} + +try { code = 'this'; } catch (e) { + // Caught! +} + +do { i = 0; +} while (i > 0); + +if (i === 0) { + + i = 1 +} + +if (window.jQuery)(function($) { + $.fn.reset = function() { + return this.each(function() { + try { + this.reset(); + } catch (e) { + } + }); + }; +})(jQuery); + +if ($("#myid").rotationDegrees()=='90') + $('.modal').css({'transform': 'rotate(90deg)'}); + +if ($("#myid").rotationDegrees()=='90') + $foo = {'transform': 'rotate(90deg)'}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed new file mode 100644 index 000000000..e3ed6de74 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed @@ -0,0 +1,141 @@ + +i = 0; +do { + i = 0; +} while (i > 0); + +do { + i = 0; +} while (i > 0); + +do { + i = 0; +} while (i > 0); + +do { +i = 0; } while (i > 0); + +do { + i = 0; +} while (i > 0); + +while (i < 1) { + i = 0; +} + +while (i < 1) { + i = 0; +} + +while (i < 1) { +i = 0; } + +for (i = 1; i < 1; i++) { + i = 0; +} + +for (i = 1; i < 1; i++) { + i = 0; +} + +for (i = 1; i < 1; i++) { +i = 0; } + +if (i == 0) { + i = 1; +} + +if (i == 0) { + i = 1; +} + +if (i == 0) { +i = 1; } + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { +i = 1; } else { +i = 0; } + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { +i = 1; } else if (i == 2) { +i = 0; } + +if (i == 0) { // comments are allowed + i = 1; +} + +if (i == 0) {// comments are allowed + i = 1; +} + +if (i == 0) { /* comments are allowed*/ + i = 1; +} + +if (i == 0) { // this is ok + i = 1; +} + +if (i == 0) { /* this is ok */ +} + +try { + code = 'this'; +} catch (e) { + // Caught! +} + +try { +code = 'this'; } catch (e) { + // Caught! +} + +do { +i = 0; +} while (i > 0); + +if (i === 0) { + + i = 1 +} + +if (window.jQuery)(function($) { + $.fn.reset = function() { + return this.each(function() { + try { + this.reset(); + } catch (e) { + } + }); + }; +})(jQuery); + +if ($("#myid").rotationDegrees()=='90') + $('.modal').css({'transform': 'rotate(90deg)'}); + +if ($("#myid").rotationDegrees()=='90') + $foo = {'transform': 'rotate(90deg)'}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php new file mode 100644 index 000000000..92427f0da --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php @@ -0,0 +1,102 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ControlSignatureUnitTest.inc') + { + $errors = [ + 7 => 1, + 12 => 1, + 15 => 1, + 18 => 1, + 20 => 1, + 22 => 2, + 28 => 2, + 32 => 1, + 38 => 2, + 42 => 1, + 48 => 2, + 52 => 1, + 62 => 2, + 66 => 2, + 76 => 4, + 80 => 2, + 94 => 1, + 99 => 1, + 108 => 1, + 112 => 1, + ]; + + if ($testFile === 'ControlSignatureUnitTest.inc') { + $errors[122] = 1; + $errors[130] = 2; + $errors[134] = 1; + $errors[150] = 1; + $errors[153] = 1; + $errors[158] = 1; + $errors[165] = 1; + $errors[170] = 2; + $errors[185] = 1; + $errors[190] = 2; + $errors[191] = 2; + $errors[195] = 1; + $errors[227] = 1; + $errors[234] = 1; + $errors[239] = 2; + $errors[243] = 2; + $errors[244] = 2; + $errors[248] = 1; + $errors[259] = 1; + $errors[262] = 1; + $errors[267] = 1; + $errors[269] = 1; + $errors[276] = 1; + $errors[279] = 1; + $errors[283] = 1; + $errors[306] = 3; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc new file mode 100644 index 000000000..91d0a23c7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ElseIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc new file mode 100644 index 000000000..4709923ee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc @@ -0,0 +1,36 @@ + $that) { +} + +// Invalid. +foreach ( $something as $blah => $that ) { +} + +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach (${something}AS$blah=>$that) { +} + +// The works. +foreach ( $something aS $blah => $that ) { +} + +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 1 +foreach ($something as $blah => $that) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 0 + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..b0de6ebcb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed @@ -0,0 +1,36 @@ + $that) { +} + +// Invalid. +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach (${something} as $blah => $that) { +} + +// The works. +foreach ($something as $blah => $that) { +} + +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 1 +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 0 + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php new file mode 100644 index 000000000..6957ff678 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForEachLoopDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 2, + 11 => 2, + 14 => 2, + 17 => 5, + 21 => 7, + 26 => 2, + 28 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc new file mode 100644 index 000000000..5022e74c9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc @@ -0,0 +1,129 @@ +i ; }; $i < function() { return $this->max; }; $i++) {} +for ($i = function() { return $this->i; }; $i < function() { return $this->max; } ; $i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines true +for ( + $i = 0; + $i < 5; + $i++ +) { + // body here +} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines false + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..6a1e7634b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inc.fixed @@ -0,0 +1,95 @@ +i ; }; $i < function() { return $this->max; }; $i++) {} +for ($i = function() { return $this->i; }; $i < function() { return $this->max; }; $i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines true +for ( + $i = 0; + $i < 5; + $i++ +) { + // body here +} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines false + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js new file mode 100644 index 000000000..cfda6c12f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js @@ -0,0 +1,125 @@ +// Valid. +for (var i = 0; i < 10; i++) { +} + +// Invalid. +for ( i = 0; i < 10; i++ ) { +} + +for (i = 0; i < 10; i++) { +} + +for (var i = 0 ; i < 10 ; i++) { +} + +for (i = 0;i < 10;i++) { +} + +// The works. +for ( var i = 0 ; i < 10 ; i++ ) { +} + +this.formats = {}; +dfx.inherits('ContentFormat', 'Widget'); + +for (var widgetid in this.loadedContents) { + if (dfx.isset(widget) === true) { + widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);}); + } +} + +for (var i = 0; i < 10;) { +} +for (var i = 0; i < 10; ) { +} + +for (var i = 0; ; i++) { +} +for (var i = 0;; i++) { +} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for (var i = 0; i < 10; i++) {} +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +for ( ; i < 10; i++) {} +for (; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} +for (; i < 10; i++ ) {} + +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10;) {} +for ( i = 0; i < 10; ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test handling of comments and inline annotations. +for ( /*phpcs:enable*/ i = 0 /*start*/ ; /*end*/i < 10/*comment*/; i++ /*comment*/ ) {} + +// Test multi-line FOR control structure. +for ( + i = 0; + i < 10; + i++ +) {} + +// Test multi-line FOR control structure with comments and annotations. +for ( + i = 0; /* Start */ + i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + i++ // comment + +) {} + +// Test fixing each error in one go. Note: lines 84 + 88 contain trailing whitespace on purpose. +for ( + + + i = 0 + + ; + + i < 10 + + ; + + i++ + + +) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( + + + + i = 0 + + ; + + i < 10 + + ; + + i++ + + +) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test with semi-colon not belonging to for. +for (i = function() {self.widgetLoaded(widget.id) ; }; i < function() {self.widgetLoaded(widget.id);}; i++) {} +for (i = function() {self.widgetLoaded(widget.id);}; i < function() {self.widgetLoaded(widget.id);} ; i++) {} + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed new file mode 100644 index 000000000..00ced6437 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js.fixed @@ -0,0 +1,91 @@ +// Valid. +for (var i = 0; i < 10; i++) { +} + +// Invalid. +for (i = 0; i < 10; i++) { +} + +for (i = 0; i < 10; i++) { +} + +for (var i = 0; i < 10; i++) { +} + +for (i = 0; i < 10; i++) { +} + +// The works. +for (var i = 0; i < 10; i++) { +} + +this.formats = {}; +dfx.inherits('ContentFormat', 'Widget'); + +for (var widgetid in this.loadedContents) { + if (dfx.isset(widget) === true) { + widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);}); + } +} + +for (var i = 0; i < 10;) { +} +for (var i = 0; i < 10;) { +} + +for (var i = 0;; i++) { +} +for (var i = 0;; i++) { +} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +for (; i < 10; i++) {} +for (; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} + +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10; ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test handling of comments and inline annotations. +for (/*phpcs:enable*/ i = 0 /*start*/; /*end*/i < 10/*comment*/; i++ /*comment*/) {} + +// Test multi-line FOR control structure. +for (i = 0; i < 10; i++) {} + +// Test multi-line FOR control structure with comments and annotations. +for (i = 0; /* Start */ + i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + i++ // comment + +) {} + +// Test fixing each error in one go. Note: lines 84 + 88 contain trailing whitespace on purpose. +for (i = 0; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test with semi-colon not belonging to for. +for (i = function() {self.widgetLoaded(widget.id) ; }; i < function() {self.widgetLoaded(widget.id);}; i++) {} +for (i = function() {self.widgetLoaded(widget.id);}; i < function() {self.widgetLoaded(widget.id);}; i++) {} + +// This test has to be the last one in the file! Intentional parse error check. +for diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php new file mode 100644 index 000000000..51638866e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php @@ -0,0 +1,132 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ForLoopDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ForLoopDeclarationUnitTest.inc') + { + switch ($testFile) { + case 'ForLoopDeclarationUnitTest.inc': + return [ + 8 => 2, + 11 => 2, + 14 => 2, + 17 => 2, + 21 => 6, + 27 => 1, + 30 => 1, + 37 => 2, + 39 => 2, + 43 => 1, + 49 => 1, + 50 => 1, + 53 => 1, + 54 => 1, + 59 => 4, + 62 => 1, + 63 => 1, + 64 => 1, + 66 => 1, + 69 => 1, + 74 => 1, + 77 => 1, + 82 => 2, + 86 => 2, + 91 => 1, + 95 => 1, + 101 => 2, + 105 => 2, + 110 => 1, + 116 => 2, + ]; + + case 'ForLoopDeclarationUnitTest.js': + return [ + 6 => 2, + 9 => 2, + 12 => 2, + 15 => 2, + 19 => 6, + 33 => 1, + 36 => 1, + 43 => 2, + 45 => 2, + 49 => 1, + 55 => 1, + 56 => 1, + 59 => 1, + 60 => 1, + 65 => 4, + 68 => 1, + 69 => 1, + 70 => 1, + 72 => 1, + 75 => 1, + 80 => 1, + 83 => 1, + 88 => 2, + 92 => 2, + 97 => 1, + 101 => 1, + 107 => 2, + 111 => 2, + 116 => 1, + 122 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='ForLoopDeclarationUnitTest.inc') + { + switch ($testFile) { + case 'ForLoopDeclarationUnitTest.inc': + return [129 => 1]; + + case 'ForLoopDeclarationUnitTest.js': + return [125 => 1]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc new file mode 100644 index 000000000..f54ed8af0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc @@ -0,0 +1,48 @@ +id.'"', + '"'.$this->stepInfo['title'].'"', + '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"', + '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"', + '"'.$this->stepInfo['title'].'"', + ); + +echo (TRUE)?'Hello':'Bye'; + +$array = array( + 'one' => ($test == 1) ? true : false, + 'two' => (($test == 1) ? true : false), + 'three' => (($test == 1) ? true : false) +); +$var = ($test == 1) ? true : false; +$var = (myFunc(1,2,3) == 1) ? true : false; + +set('config', function() { + $foo = ($bar === "on") ? "1" : "2"; +}); + +$config = function() { + $foo = ($bar === "on") ? "1" : "2"; +}; + +rand(0, 1) ? 'ěščřžýáí' : NULL; + +$c = ($argv[1]) ? : ""; +$filepath = realpath($argv[1]) ?: $argv[1]; +$c = ($argv[1]) ? /* comment */ : ""; +$c = ($argv[1]) ? +: ""; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..f7aa1d67c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed @@ -0,0 +1,48 @@ +id.'"', + '"'.$this->stepInfo['title'].'"', + '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"', + '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"', + '"'.$this->stepInfo['title'].'"', + ); + +echo (TRUE) ? 'Hello' : 'Bye'; + +$array = array( + 'one' => ($test == 1) ? true : false, + 'two' => (($test == 1) ? true : false), + 'three' => (($test == 1) ? true : false) +); +$var = ($test == 1) ? true : false; +$var = (myFunc(1,2,3) == 1) ? true : false; + +set('config', function() { + $foo = ($bar === "on") ? "1" : "2"; +}); + +$config = function() { + $foo = ($bar === "on") ? "1" : "2"; +}; + +rand(0, 1) ? 'ěščřžýáí' : NULL; + +$c = ($argv[1]) ?: ""; +$filepath = realpath($argv[1]) ?: $argv[1]; +$c = ($argv[1]) ? /* comment */ : ""; +$c = ($argv[1]) ? +: ""; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php new file mode 100644 index 000000000..97212dbaf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InlineIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getCliValues($testFile) + { + return ['--encoding=utf-8']; + + }//end getCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 13 => 1, + 20 => 1, + 24 => 4, + 44 => 1, + 47 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc new file mode 100644 index 000000000..1acf3eac4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc @@ -0,0 +1,24 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 12 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 20 => 1, + 21 => 1, + 24 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc new file mode 100644 index 000000000..cf397607b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc @@ -0,0 +1,333 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SwitchDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='SwitchDeclarationUnitTest.inc') + { + switch ($testFile) { + case 'SwitchDeclarationUnitTest.inc': + return [ + 27 => 1, + 29 => 1, + 34 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 52 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 62 => 1, + 79 => 1, + 85 => 2, + 88 => 2, + 89 => 2, + 92 => 1, + 95 => 3, + 99 => 1, + 116 => 1, + 122 => 1, + 127 => 2, + 134 => 2, + 135 => 1, + 138 => 1, + 143 => 1, + 144 => 1, + 147 => 1, + 165 => 1, + 172 => 1, + 176 => 2, + 180 => 1, + 192 => 2, + 196 => 1, + 223 => 1, + 266 => 1, + 282 => 1, + 284 => 2, + 322 => 1, + 323 => 1, + 327 => 1, + 329 => 1, + 330 => 1, + ]; + + case 'SwitchDeclarationUnitTest.js': + return [ + 27 => 1, + 29 => 1, + 34 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 52 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 62 => 1, + 79 => 1, + 85 => 2, + 88 => 2, + 89 => 2, + 92 => 1, + 95 => 3, + 99 => 1, + 116 => 1, + 122 => 1, + 127 => 2, + 134 => 2, + 135 => 1, + 138 => 1, + 143 => 1, + 144 => 1, + 147 => 1, + 165 => 1, + 172 => 1, + 176 => 2, + 180 => 1, + 192 => 2, + 196 => 1, + 223 => 1, + 266 => 1, + 282 => 1, + 284 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='SwitchDeclarationUnitTest.inc') + { + if ($testFile === 'SwitchDeclarationUnitTest.js') { + return [273 => 1]; + } + + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js new file mode 100644 index 000000000..797e0eea2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js @@ -0,0 +1,2 @@ +alert('hi') +alert('hi'); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php new file mode 100644 index 000000000..7ccfe1a31 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +class JSLintUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + $jslPath = Config::getExecutablePath('jslint'); + if ($jslPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 1 => 2, + 2 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js new file mode 100644 index 000000000..797e0eea2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js @@ -0,0 +1,2 @@ +alert('hi') +alert('hi'); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php new file mode 100644 index 000000000..1e83f1f40 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +class JavaScriptLintUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + $jslPath = Config::getExecutablePath('jsl'); + if ($jslPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc new file mode 100644 index 000000000..3279edb54 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc new file mode 100644 index 000000000..05be63306 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc new file mode 100644 index 000000000..ec1b02390 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc new file mode 100644 index 000000000..ed0456463 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc new file mode 100644 index 000000000..d777aff6b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php new file mode 100644 index 000000000..7e613b330 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FileExtensionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileExtensionUnitTest.1.inc': + return [1 => 1]; + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc new file mode 100644 index 000000000..2a480bb92 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc @@ -0,0 +1,195 @@ +words[$wordPos-1]) || $this->words[$wordPos-1] !== ' ') { +} else if ($this->tokens[$pos + 1] === "\n") { +} + +if ($pos === count($this->tokens) - 1) { + $file = '...'.substr($file, (($padding * -1) + 3)); +} + +if (substr($basename, -5) !== 'Sniff') { + $i = ($this->_tokens[$i]['parenthesis_closer'] + 1); +} + +$pos = $this->_getShortCommentEndPos(); +if ($pos === -1) { + $stackPtr = ($tokens[$next][$to] - 1); + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + $var = (($var1 + $var2) + $var3 + $var4) +} + +$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); +$commentEnd = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1); +$expected .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content']; + +if (($tokens[$nextToken - 1]['code']) !== T_WHITESPACE) { + $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart); +} + +while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, $nextSpace + 1, $nextBreak)) !== false) { +} + +foreach ($attributes as $id => &$attribute) { +} + +class MyClass +{ + + + public function &myFunction(array &$one, array &$two) + { + + }//end myFunction() + + +}//end class + +if ($index < -1) $index = 0; +if ($index < - 1) $index = 0; + +$three = ceil($one / $two); +$three = ceil(($one / $two) / $four); +$three = ceil($one / ($two / $four)); + +$four = -0.25; + +$three = ceil($one[1] / $two); + +switch ($number % 10) { + case -1: + $suffix = 'st'; + break; +} + +$expectedPermission = array( + 'granted' => 4, + 'denied' => 1, + 'cascade' => TRUE, + 'blockergranted' => 2, + 'blockerdenied' => - 3, + 'effective' => TRUE, + ); + +$value = (int) isset($blah) + 2; +$value = (int) isset($blah) + (int) isset($foo) + (int) isset($bar); + +doSomething(getValue($var, 2)) - $y; + +$codeFiles = array($global => $codeFiles[$global]) + $codeFiles; + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$cntPages = ceil(count($items) / self::ON_PAGE); + +error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); +error_reporting(E_ALL & ~E_NOTICE | ~E_WARNING); +$results = $stmt->fetchAll(\PDO::FETCH_ASSOC | \PDO::FETCH_GROUP | \PDO::FETCH_UNIQUE); +$di = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS); +foo(1 + 2 + 3); + +if (empty($foo[-1]) === true) { + $foo[-1] = 'foo'; +} + +try { +} catch (AException | BException $e) { +} + +$var = $foo['blah'] + []; + +$a = 2 * ${x} - ${minus}; + +$foo = $bar ?? $baz ?? ''; + +$foo = $myString{-1}; + +$value = (binary) $blah + b"binary $foo"; + +$test = (1 * static::TEST); +$test = myfunc(1 * static::TEST); + +$errorPos = $params[$x]?->getLine() + $commentStart; + +$foo = $this->gmail ?? $this->gmail = new Google_Service_Gmail($this->google); + +exit -1; + +$expr = match ($number - 10) { + -1 => 0, +}; + +$expr = match ($number % 10) { + 1 => 2 * $num, +}; + +$expr = match (true) { + $num * 100 > 500 => 'expression in key', +}; + +// PHP 8.0 named parameters. +if ($pos === count(value: $this->tokens) - 1) { + $file = '...'.substr(string: $file, offset: $padding * -1 + 3); +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed new file mode 100644 index 000000000..669b16b2b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc.fixed @@ -0,0 +1,195 @@ +words[($wordPos-1)]) || $this->words[($wordPos-1)] !== ' ') { +} else if ($this->tokens[($pos + 1)] === "\n") { +} + +if ($pos === (count($this->tokens) - 1)) { + $file = '...'.substr($file, (($padding * -1) + 3)); +} + +if (substr($basename, -5) !== 'Sniff') { + $i = ($this->_tokens[$i]['parenthesis_closer'] + 1); +} + +$pos = $this->_getShortCommentEndPos(); +if ($pos === -1) { + $stackPtr = ($tokens[$next][$to] - 1); + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + $var = (($var1 + $var2) + $var3 + $var4) +} + +$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); +$commentEnd = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1); +$expected .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content']; + +if (($tokens[($nextToken - 1)]['code']) !== T_WHITESPACE) { + $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart); +} + +while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, ($nextSpace + 1), $nextBreak)) !== false) { +} + +foreach ($attributes as $id => &$attribute) { +} + +class MyClass +{ + + + public function &myFunction(array &$one, array &$two) + { + + }//end myFunction() + + +}//end class + +if ($index < -1) $index = 0; +if ($index < - 1) $index = 0; + +$three = ceil($one / $two); +$three = ceil(($one / $two) / $four); +$three = ceil($one / ($two / $four)); + +$four = -0.25; + +$three = ceil($one[1] / $two); + +switch ($number % 10) { + case -1: + $suffix = 'st'; + break; +} + +$expectedPermission = array( + 'granted' => 4, + 'denied' => 1, + 'cascade' => TRUE, + 'blockergranted' => 2, + 'blockerdenied' => - 3, + 'effective' => TRUE, + ); + +$value = ((int) isset($blah) + 2); +$value = ((int) isset($blah) + (int) isset($foo) + (int) isset($bar)); + +(doSomething(getValue($var, 2)) - $y); + +$codeFiles = (array($global => $codeFiles[$global]) + $codeFiles); + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$cntPages = ceil(count($items) / self::ON_PAGE); + +error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); +error_reporting(E_ALL & ~E_NOTICE | ~E_WARNING); +$results = $stmt->fetchAll(\PDO::FETCH_ASSOC | \PDO::FETCH_GROUP | \PDO::FETCH_UNIQUE); +$di = new \RecursiveDirectoryIterator($path, (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)); +foo(1 + 2 + 3); + +if (empty($foo[-1]) === true) { + $foo[-1] = 'foo'; +} + +try { +} catch (AException | BException $e) { +} + +$var = ($foo['blah'] + []); + +$a = 2 * ${x} - ${minus}; + +$foo = ($bar ?? $baz ?? ''); + +$foo = $myString{-1}; + +$value = ((binary) $blah + b"binary $foo"); + +$test = (1 * static::TEST); +$test = myfunc(1 * static::TEST); + +$errorPos = ($params[$x]?->getLine() + $commentStart); + +$foo = ($this->gmail ?? $this->gmail = new Google_Service_Gmail($this->google)); + +exit -1; + +$expr = match ($number - 10) { + -1 => 0, +}; + +$expr = match ($number % 10) { + 1 => (2 * $num), +}; + +$expr = match (true) { + ($num * 100) > 500 => 'expression in key', +}; + +// PHP 8.0 named parameters. +if ($pos === (count(value: $this->tokens) - 1)) { + $file = '...'.substr(string: $file, offset: ($padding * -1 + 3)); +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js new file mode 100644 index 000000000..92ed8038a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js @@ -0,0 +1,118 @@ +value = (one + two); +value = one + two; + +value = (one - two); +value = one - two; + +value = (one * two); +value = one * two; + +value = (one / two); +value = one / two; + +value = (one % two); +value = one % two; + +value = (one + two + three); +value = one + two + three; +value = (one + (two + three)); +value = one + (two + three); + +value++; +value--; +value = -1; +value = - 1; + +value = (1 + 2); +value = 1 + 2; + +value = (1 - 2); +value = 1 - 2; + +value = (1 * 2); +value = 1 * 2; + +value = (1 / 2); +value = 1 / 2; + +value = (1 % 2); +value = 1 % 2; + +value = (1 + 2 + 3); +value = 1 + 2 + 3; +value = (1 + (2 + 3)); +value = 1 + (2 + 3); + +value = one + 2 + 3 - (four * five * (6 + 7)) + nine + 2; +value = myFunction(tokens[stackPtr - 1]); + +for (i = 1 + 2; i < 4 + 5; i++) { +} + +function myFunction() +{ + value = (one + 1) + (two + 2) + (myFunction() + 2); + value = myFunction() + 2; + value = (myFunction(mvar) + myFunction2(mvar)); + return -1; +} + +params['mode'] = id.replace(/WidgetType/, ''); + +if (index < -1) index = 0; +if (index < - 1) index = 0; + +var classN = prvId.replace(/\./g, '-'); + +three = myFunction(one / two); +three = myFunction((one / two) / four); +three = myFunction(one / (two / four)); + +four = -0.25; + +id = id.replace(/row\/:/gi, ''); +return /MSIE/.test(navigator.userAgent); + +var re = new RegExp(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gim); + +var options = { + minVal: -1, + maxVal: -1 +}; + +stepWidth = Math.round(this.width / 5); + +date.setMonth(d[2] - 1); + +switch (number % 10) { + case -1: + suffix = 'st'; + break; +} + +var pathSplit = ipt.value.split(/\/|\\/); + +if (pairs[i].search(/=/) !== -1) { +} + +if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) { +} + +if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) { +} + +if (!value || /^\s*$/.test(value)) { + return true; +} + +parseInt(dfx.attr(selectors[idx], 'elemOffsetTop'), 10) - scrollCoords.y + 'px' + +if (something === true + ^ somethingElse === true +) { + return false; +} + +if (true === /^\d*\.?\d*$/.test(input)) return true; + +if ( ! /^(?:a|select)$/i.test( element.tagName ) ) return true; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed new file mode 100644 index 000000000..04e35d977 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed @@ -0,0 +1,118 @@ +value = (one + two); +value = one + two; + +value = (one - two); +value = (one - two); + +value = (one * two); +value = (one * two); + +value = (one / two); +value = (one / two); + +value = (one % two); +value = (one % two); + +value = (one + two + three); +value = one + two + three; +value = (one + (two + three)); +value = one + (two + three); + +value++; +value--; +value = -1; +value = - 1; + +value = (1 + 2); +value = 1 + 2; + +value = (1 - 2); +value = (1 - 2); + +value = (1 * 2); +value = (1 * 2); + +value = (1 / 2); +value = (1 / 2); + +value = (1 % 2); +value = (1 % 2); + +value = (1 + 2 + 3); +value = 1 + 2 + 3; +value = (1 + (2 + 3)); +value = 1 + (2 + 3); + +value = one + 2 + (3 - (four * five * (6 + 7))) + nine + 2; +value = myFunction(tokens[(stackPtr - 1)]); + +for (i = 1 + 2; i < 4 + 5; i++) { +} + +function myFunction() +{ + value = (one + 1) + (two + 2) + (myFunction() + 2); + value = myFunction() + 2; + value = (myFunction(mvar) + myFunction2(mvar)); + return -1; +} + +params['mode'] = id.replace(/WidgetType/, ''); + +if (index < -1) index = 0; +if (index < - 1) index = 0; + +var classN = prvId.replace(/\./g, '-'); + +three = myFunction(one / two); +three = myFunction((one / two) / four); +three = myFunction(one / (two / four)); + +four = -0.25; + +id = id.replace(/row\/:/gi, ''); +return /MSIE/.test(navigator.userAgent); + +var re = new RegExp(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gim); + +var options = { + minVal: -1, + maxVal: -1 +}; + +stepWidth = Math.round(this.width / 5); + +date.setMonth(d[2] - 1); + +switch (number % 10) { + case -1: + suffix = 'st'; + break; +} + +var pathSplit = ipt.value.split(/\/|\\/); + +if (pairs[i].search(/=/) !== -1) { +} + +if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) { +} + +if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) { +} + +if (!value || /^\s*$/.test(value)) { + return true; +} + +(parseInt(dfx.attr(selectors[idx], 'elemOffsetTop'), 10) - scrollCoords.y) + 'px' + +if (something === true + ^ somethingElse === true +) { + return false; +} + +if (true === /^\d*\.?\d*$/.test(input)) return true; + +if ( ! /^(?:a|select)$/i.test( element.tagName ) ) return true; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php new file mode 100644 index 000000000..4f04a6ebd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Formatting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OperatorBracketUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='OperatorBracketUnitTest.inc') + { + switch ($testFile) { + case 'OperatorBracketUnitTest.inc': + return [ + 3 => 1, + 6 => 1, + 9 => 1, + 12 => 1, + 15 => 1, + 18 => 2, + 20 => 1, + 25 => 1, + 28 => 1, + 31 => 1, + 34 => 1, + 37 => 1, + 40 => 1, + 43 => 2, + 45 => 1, + 47 => 5, + 48 => 1, + 50 => 2, + 55 => 2, + 56 => 1, + 63 => 2, + 64 => 1, + 67 => 1, + 86 => 1, + 90 => 1, + 109 => 1, + 130 => 1, + 134 => 1, + 135 => 2, + 137 => 1, + 139 => 1, + 150 => 1, + 161 => 1, + 163 => 2, + 165 => 2, + 169 => 1, + 174 => 1, + 176 => 1, + 185 => 1, + 189 => 1, + 193 => 1, + 194 => 2, + ]; + break; + case 'OperatorBracketUnitTest.js': + return [ + 5 => 1, + 8 => 1, + 11 => 1, + 14 => 1, + 24 => 1, + 30 => 1, + 33 => 1, + 36 => 1, + 39 => 1, + 46 => 1, + 47 => 1, + 63 => 1, + 108 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc new file mode 100644 index 000000000..33564e2e0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc @@ -0,0 +1,111 @@ + $a($b); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..68fb1c1c3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed @@ -0,0 +1,111 @@ + $a($b); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php new file mode 100644 index 000000000..65e987dda --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDeclarationArgumentSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 2, + 7 => 2, + 8 => 2, + 9 => 2, + 11 => 2, + 13 => 7, + 14 => 2, + 15 => 2, + 16 => 4, + 18 => 2, + 35 => 2, + 36 => 2, + 44 => 2, + 45 => 1, + 46 => 1, + 51 => 2, + 53 => 2, + 55 => 1, + 56 => 1, + 58 => 1, + 73 => 7, + 76 => 1, + 77 => 1, + 81 => 1, + 89 => 2, + 92 => 1, + 93 => 1, + 94 => 1, + 95 => 1, + 99 => 11, + 100 => 2, + 101 => 2, + 102 => 2, + 106 => 1, + 107 => 2, + 111 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc new file mode 100644 index 000000000..0cde1138c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 55 => 1, + 68 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc new file mode 100644 index 000000000..27102d057 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php new file mode 100644 index 000000000..da09cef34 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionDuplicateArgumentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 2, + 5 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc new file mode 100644 index 000000000..b7b7f205c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc @@ -0,0 +1,17 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php new file mode 100644 index 000000000..7be76488e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GlobalFunctionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc new file mode 100644 index 000000000..4e8683362 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc @@ -0,0 +1,28 @@ + $x; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed new file mode 100644 index 000000000..48c997774 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed @@ -0,0 +1,28 @@ + $x; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php new file mode 100644 index 000000000..1e1537b7d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercaseFunctionKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 16 => 1, + 17 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 24 => 3, + 25 => 4, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc new file mode 100644 index 000000000..fce0b237b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc @@ -0,0 +1,257 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MultiLineFunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='MultiLineFunctionDeclarationUnitTest.inc') + { + if ($testFile === 'MultiLineFunctionDeclarationUnitTest.inc') { + $errors = [ + 2 => 1, + 3 => 1, + 4 => 2, + 5 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 36 => 1, + 43 => 2, + 48 => 1, + 81 => 1, + 82 => 2, + 88 => 1, + 102 => 2, + 137 => 1, + 141 => 2, + 142 => 1, + 158 => 1, + 160 => 1, + 182 => 2, + 186 => 2, + 190 => 2, + 194 => 1, + 195 => 1, + 233 => 1, + 234 => 1, + 235 => 1, + 236 => 1, + 244 => 1, + 245 => 1, + 246 => 1, + 247 => 1, + 248 => 1, + 249 => 1, + 250 => 1, + 251 => 1, + 252 => 1, + 253 => 1, + 254 => 1, + ]; + } else { + $errors = [ + 2 => 1, + 3 => 1, + 4 => 2, + 5 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 26 => 1, + 36 => 1, + 43 => 2, + 48 => 1, + 65 => 1, + ]; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc new file mode 100644 index 000000000..aacef347b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -0,0 +1,27 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php new file mode 100644 index 000000000..77f13bb25 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidFunctionNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 000000000..87c3bdf2e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,157 @@ +varName2; +echo $this->var_name2; +echo $this->varname2; +echo $this->_varName2; +echo $object->varName2; +echo $object->var_name2; +echo $object_name->varname2; +echo $object_name->_varName2; + +echo $this->myFunction($one, $two); +echo $object->myFunction($one_two); + +$error = "format is \$GLOBALS['$varName']"; + +echo $_SESSION['var_name']; +echo $_FILES['var_name']; +echo $_ENV['var_name']; +echo $_COOKIE['var_name']; + +$XML = 'hello'; +$myXML = 'hello'; +$XMLParser = 'hello'; +$xmlParser = 'hello'; + +echo "{$_SERVER['HOSTNAME']} $var_name"; + +// Need to be the last thing in this test file. +$obj->$classVar = $prefix.'-'.$type; + +class foo +{ + const bar = <<varName; +echo $obj?->var_name; +echo $obj?->varname; +echo $obj?->_varName; + +enum SomeEnum +{ + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 000000000..9acbe241a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 3 => 1, + 5 => 1, + 10 => 1, + 12 => 1, + 15 => 1, + 17 => 1, + 20 => 1, + 22 => 1, + 25 => 1, + 27 => 1, + 31 => 1, + 33 => 1, + 36 => 1, + 37 => 1, + 39 => 1, + 42 => 1, + 44 => 1, + 53 => 1, + 58 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 67 => 1, + 81 => 1, + 106 => 1, + 107 => 2, + 108 => 1, + 111 => 1, + 112 => 1, + 113 => 1, + 114 => 1, + 123 => 1, + 138 => 1, + 141 => 1, + 146 => 1, + 152 => 1, + 155 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js new file mode 100644 index 000000000..1c61fbfbb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js @@ -0,0 +1,37 @@ +function test(id) +{ + + this.id = id; + +} +/**/ +test.prototype = { + init: function() + { + var x = {}; + x.name = 'test'; + x['phone'] = 123124324; + var t = ['test', 'this'].join(''); + var y = ['test'].join(''); + var a = x[0]; + var z = x[x['name']]; + var p = x[x.name]; + } + +}; + +function test() { + this.errors['step_' + step] = errors; + this.errors['test'] = x; + this.errors['test' + 10] = x; + this.errors['test' + y] = x; + this.errors['test' + 'blah'] = x; + this.errors[y] = x; + this.errors[y + z] = x; + this.permissions['workflow.cancel'] = x; +} + +if (child.prototype) { + above.prototype['constructor'] = parent; + child.prototype['super'] = new above(); +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php new file mode 100644 index 000000000..cb2d58e54 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowObjectStringIndexUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowObjectStringIndexUnitTest.js') + { + if ($testFile !== 'DisallowObjectStringIndexUnitTest.js') { + return []; + } + + return [ + 13 => 1, + 17 => 1, + 25 => 1, + 35 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc new file mode 100644 index 000000000..41c881289 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc @@ -0,0 +1,46 @@ + new MyClass()); +$object->myFunction(new MyClass()); + +throw new MyException($msg); + +function foo() { return new MyClass(); } + +$doodad = $x ? new Foo : new Bar; + +function returnFn() { + $fn = fn($x) => new MyClass(); +} + +function returnMatch() { + $match = match($x) { + 0 => new MyClass() + } +} + +// Issue 3333. +$time2 ??= new \DateTime(); +$time3 = $time1 ?? new \DateTime(); +$time3 = $time1 ?? $time2 ?? new \DateTime(); + +function_call($time1 ?? new \DateTime()); +$return = function_call($time1 ?? new \DateTime()); // False negative depending on interpretation of the sniff. + +function returnViaTernary() { + return ($y == false ) ? ($x === true ? new Foo : new Bar) : new FooBar; +} + +function nonAssignmentTernary() { + if (($x ? new Foo() : new Bar) instanceof FooBar) { + // Do something. + } +} + +// Intentional parse error. This must be the last test in the file. +function new +?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php new file mode 100644 index 000000000..f9979fa29 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectInstantiationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 8 => 1, + 31 => 1, + 39 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js new file mode 100644 index 000000000..28bf85ade --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js @@ -0,0 +1,47 @@ +this.request({ action: 'getTypeFormatContents', }); + +addTypeFormatButton.addClickEvent(function() { + self.addNewTypeFormat(); +}); + +var x = {}; + +var y = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var z = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + }, +}; + +var x = function() { + console.info(2); +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + }, +}; + +AssetListingEditWidgetType.prototype = { + // phpcs: disable Standard.Cat.SniffName -- testing annotation between closing brace and comma + init: function(data, assetid, editables) + { + }, + // phpcs:enable +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed new file mode 100644 index 000000000..df548c741 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed @@ -0,0 +1,47 @@ +this.request({ action: 'getTypeFormatContents' }); + +addTypeFormatButton.addClickEvent(function() { + self.addNewTypeFormat(); +}); + +var x = {}; + +var y = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var z = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var x = function() { + console.info(2); +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + // phpcs: disable Standard.Cat.SniffName -- testing annotation between closing brace and comma + init: function(data, assetid, editables) + { + } + // phpcs:enable +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php new file mode 100644 index 000000000..ab1cf8108 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectMemberCommaUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 1 => 1, + 22 => 1, + 38 => 1, + 45 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc new file mode 100644 index 000000000..8522438dc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc @@ -0,0 +1,138 @@ + + 0)) { +} + +myFunction($var1 === true ? "" : "foobar"); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js new file mode 100644 index 000000000..048223ba1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js @@ -0,0 +1,71 @@ +if (value === TRUE) { +} else if (value === FALSE) { +} + +if (value == TRUE) { +} else if (value == FALSE) { +} + +if (value) { +} else if (!value) { +} + +if (value.isSomething === TRUE) { +} else if (myFunction(value) === FALSE) { +} + +if (value.isSomething == TRUE) { +} else if (myFunction(value) == FALSE) { +} + +if (value.isSomething) { +} else if (!myFunction(value)) { +} + +if (value === TRUE || other === FALSE) { +} + +if (value == TRUE || other == FALSE) { +} + +if (value || !other) { +} + +if (one === TRUE || two === TRUE || three === FALSE || four === TRUE) { +} + +if (one || two || !three || four) { +} + +while (one == true) { +} + +while (one === true) { +} + +do { +} while (one == true); + +do { +} while (one === true); + +for (one = 10; one != 0; one--) { +} + +for (one = 10; one !== 0; one--) { +} + +for (type in types) { +} + +variable = (variable2 === true) ? variable1 : "foobar"; + +variable = (variable2 == true) ? variable1 : "foobar"; + +variable = (variable2 === false) ? variable1 : "foobar"; + +variable = (variable2 == false) ? variable1 : "foobar"; + +variable = (variable2 === 0) ? variable1 : "foobar"; + +variable = (variable2 == 0) ? variable1 : "foobar"; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php new file mode 100644 index 000000000..5618a7fc0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php @@ -0,0 +1,101 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ComparisonOperatorUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ComparisonOperatorUsageUnitTest.inc') + { + switch ($testFile) { + case 'ComparisonOperatorUsageUnitTest.inc': + return [ + 6 => 1, + 7 => 1, + 10 => 1, + 11 => 1, + 18 => 1, + 19 => 1, + 22 => 1, + 23 => 1, + 29 => 2, + 32 => 2, + 38 => 4, + 47 => 2, + 69 => 1, + 72 => 1, + 75 => 1, + 78 => 1, + 80 => 1, + 82 => 1, + 83 => 1, + 89 => 1, + 92 => 1, + 100 => 1, + 106 => 1, + 112 => 1, + 123 => 1, + 127 => 1, + 131 => 1, + 135 => 1, + ]; + break; + case 'ComparisonOperatorUsageUnitTest.js': + return [ + 5 => 1, + 6 => 1, + 17 => 1, + 18 => 1, + 28 => 2, + 40 => 1, + 47 => 1, + 52 => 1, + 63 => 1, + 67 => 1, + 71 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc new file mode 100644 index 000000000..a4f82d1a8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc @@ -0,0 +1,42 @@ +i++).$id; +$id = $obj?->i++.$id; +$id = $obj?->i++*10; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php new file mode 100644 index 000000000..3846905da --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class IncrementDecrementUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 6 => 1, + 12 => 1, + 16 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + 41 => 1, + 42 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc new file mode 100644 index 000000000..328ccc5d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc @@ -0,0 +1,28 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php new file mode 100644 index 000000000..fc3513198 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidLogicalOperatorsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 11 => 1, + 17 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css new file mode 100644 index 000000000..94cc8f27c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css @@ -0,0 +1,23 @@ +/* CSS Document */ + +body { +font-family: Arial, Helvetica, sans-serif; +margin : 40px 0 0 0; +padding : 0; +/*background: #8FB7DB url(login_glow_bg.jpg) no-repeat 30% 0;*/ +background: #8FB7DB url(diag_lines_bg.gif) top left; +} + +#login-container { + margin-left: -225px; + margin-top: -161px; + position:absolute; + top :50%; + /*left :50%;*/ + width:450px; +} + +#cacheConfig-dayLabel, #cacheConfig-hourLabel, #cacheConfig-minuteLabel { + float: left; + padding-right: 8px; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc new file mode 100644 index 000000000..121240a94 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc @@ -0,0 +1,158 @@ + + * + * Title + * Contents + * + * ... + * + * + * + * + * @return void + */ + +/* + [^\'"] +*/ + +// http://www.google.com + +// Base config function. + +// function () + +// T_STRING is not a function call or not listed in _getFunctionListWithCallableArgument(). + + // function myFunction( $param ) + // { + // do_something(); + // }//end myFunction() + // + +/* +function myFunction( $param ) +{ + // phpcs:disable Standard.Category.Sniff -- for reasons. + if ( preg_match( '`[abc]`', $param ) > 0 ) { + do_something(); + } + // phpcs:enable Standard.Category.Sniff -- for reasons. + +}//end myFunction() +*/ + + /* + * function myFunction( $param ) // @phpcs:ignore Standard.Category.Sniff -- for reasons. + * { + * + * }//end myFunction() + */ + + /* + * function myFunction( $param ) + * { + * // phpcs:disable Standard.Category.Sniff -- for reasons. + * if ( preg_match( '`[abc]`', $param ) > 0 ) { + * do_something(); + * } + * // phpcs:enable Standard.Category.Sniff -- for reasons. + * + * }//end myFunction() + */ + + // function myFunction( $param ) + // { + // phpcs:disable Standard.Category.Sniff -- for reasons. + // do_something(); + // phpcs:enable Standard.Category.Sniff -- for reasons. + // }//end myFunction() + // + +echo 'something'; // @codeCoverageIgnore +echo 'something'; // @codeCoverageIgnoreStart +echo 'something'; // @SuppressWarnings(PHPMD.UnusedLocalVariable) + +// Ok! + +/* Go! */ + +// ISO-639-3 + + // But override with a different text if any. + /* + $id = intval( str_replace( 'hook_name', '', $order_method['method_id'] ) ); + if ( ! empty( $id ) ) { + $info_text = get_post_meta( $location_id, 'meta_name' ); + + if ( ! empty( $info_text ) ) { + $text = $info_text; + } + + } + */ + // function() { $a = $b; }; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php new file mode 100644 index 000000000..36c556d8c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CommentedOutCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='CommentedOutCodeUnitTest.inc') + { + switch ($testFile) { + case 'CommentedOutCodeUnitTest.inc': + return [ + 6 => 1, + 8 => 1, + 15 => 1, + 19 => 1, + 87 => 1, + 91 => 1, + 97 => 1, + 109 => 1, + 116 => 1, + 128 => 1, + 147 => 1, + 158 => 1, + ]; + break; + case 'CommentedOutCodeUnitTest.css': + return [ + 7 => 1, + 16 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc new file mode 100644 index 000000000..4701c23e9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php new file mode 100644 index 000000000..6439b6323 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowBooleanStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 8 => 1, + 13 => 1, + 15 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc new file mode 100644 index 000000000..022aca739 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc @@ -0,0 +1,73 @@ +nextSibling; $node; $node = $node->nextSibling) { + if ($node->nodeType !== XML_ELEMENT_NODE) { + continue; + } + + for ($node = $fields->nextSibling; $node; $node = $node->nextSibling) { + if ($node->nodeType !== XML_ELEMENT_NODE) { + continue; + } + } +} + +$a = $b ? $c : $d; +$a = $b === true ? $c : $d; + +$this->_args = $this->_getArgs(($_SERVER['argv'] ?? [])); +$args = ($_SERVER['argv'] ?? []); + +$a = [ + 'a' => ($foo) ? $foo : $bar, +]; + +$a = [ + 'a' => ($foo) ? fn() => return 1 : fn() => return 2, +]; + +$var = $foo->something(!$var); +$var = $foo?->something(!$var); + +$callback = function ($value) { + if ($value > 10) { + return false; + } +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php new file mode 100644 index 000000000..c8d8b0b87 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowComparisonAssignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 10 => 1, + 52 => 1, + 53 => 1, + 58 => 1, + 62 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc new file mode 100644 index 000000000..f57e07109 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc @@ -0,0 +1,18 @@ + $x; + +$b = fn ($b) => $b ? true : false; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js new file mode 100644 index 000000000..56387c06f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js @@ -0,0 +1,2 @@ +x = (x?a:x); +id = id.replace(/row\/:/gi, ''); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php new file mode 100644 index 000000000..27083ce2c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowInlineIfUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowInlineIfUnitTest.inc') + { + switch ($testFile) { + case 'DisallowInlineIfUnitTest.inc': + return [ + 8 => 1, + 18 => 1, + ]; + break; + case 'DisallowInlineIfUnitTest.js': + return [1 => 1]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc new file mode 100644 index 000000000..f657fb4a4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc @@ -0,0 +1,110 @@ +fetch(PDO::FETCH_NUM)) { + $result[$row[0]] = array(); + $result[$row[0]][] = $current; + + self::$_inTransaction = TRUE; + parent::$_inTransaction = TRUE; + static::$_inTransaction = TRUE; + $$varName = $varValue; + } + +}//end getVar() + +class myClass +{ + private static $_dbh = NULL; + public $dbh = NULL; + protected $dbh = NULL; + var $dbh = NULL; // Old PHP4 compatible code. +} + +A::$a = 'b'; +\A::$a = 'c'; +\A\B\C::$d = 'd'; +B\C::$d = 'e'; + +@$a = 1; + +$a = []; +foreach ($a as $b) + $c = 'd'; + +$var = $var2; +list ($a, $b) = explode(',', $c); +$var1 ? $var2 = 0 : $var2 = 1; + +$obj->$classVar = $prefix.'-'.$type; + +$closureWithDefaultParamter = function(array $testArray=array()) {}; +?> + + + 10, + false => 0 + }, +]; + +$arrow_function = fn ($a = null) => $a; + +function ($html) { + $regEx = '/regexp/'; + + return preg_replace_callback($regEx, function ($matches) { + [$all] = $matches; + return $all; + }, $html); +}; + + +function () { + $a = false; + + some_label: + + $b = getB(); +}; + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php new file mode 100644 index 000000000..618d76efa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowMultipleAssignmentsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 2, + 7 => 1, + 9 => 1, + 12 => 1, + 14 => 1, + 15 => 1, + 79 => 1, + 85 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc new file mode 100644 index 000000000..56802e37a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc @@ -0,0 +1,58 @@ +children); $i++) { +} + + + +for ($i = 0; $i < sizeof($array); $i++) { +} + +$num = sizeof($array); + +while ($i < sizeof($array)) { +} + +do { +} while ($i < sizeof($array)); + +for ($i = 0; $i < sizeof($this->children); $i++) { +} + + + + +for ($i = 0; $i < strlen($string); $i++) { +} + +$num = strlen($string); + +while ($i < strlen($string)) { +} + +do { +} while ($i < strlen($string)); + +for ($i = 0; $i < strlen($this->string); $i++) { +} + +for ($i = sizeof($array); $i > 0; $i--) { +} + +do { + echo $a->count; + $a->count--; +} while($a->count); + +for ($i = 0; $i < $a->count; $i++) {} +for ($i = 0; $i < $a?->count; $i++) {} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js new file mode 100644 index 000000000..8f7f7b94f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js @@ -0,0 +1,13 @@ +for (var i = 0; i < permissions.length; i++) { + // Code here. +} + +var permLen = permissions.length; +for (var length = 0; i < permLen; i++) { + // Code here. +} + +var myArray = [1, 2, 3, 4]; +for (var i = myArray.length; i >= 0; i--) { + var x = i; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php new file mode 100644 index 000000000..21260ad71 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DisallowSizeFunctionsInLoopsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='DisallowSizeFunctionsInLoopsUnitTest.inc') + { + switch ($testFile) { + case 'DisallowSizeFunctionsInLoopsUnitTest.inc': + return [ + 2 => 1, + 7 => 1, + 11 => 1, + 13 => 1, + 18 => 1, + 23 => 1, + 27 => 1, + 29 => 1, + 35 => 1, + 40 => 1, + 44 => 1, + 46 => 1, + ]; + break; + case 'DisallowSizeFunctionsInLoopsUnitTest.js': + return [1 => 1]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc new file mode 100644 index 000000000..ca457a2e9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc @@ -0,0 +1,5 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php new file mode 100644 index 000000000..2b2ff5b4a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DiscouragedFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc new file mode 100644 index 000000000..c61d5a391 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc @@ -0,0 +1,119 @@ + + + +<?php echo $title ?> + + + + + hello + + + + + + + + + + + + + + + + + + + + + +section as $section) { + ?> + + + + + + section as $section) { + ?> +
    + + + + + + + + +?> + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed new file mode 100644 index 000000000..5b43d8493 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc.fixed @@ -0,0 +1,119 @@ + + + +<?php echo $title; ?> + + + + + hello + + + + + + + + + + + + + + + + + + + +section as $section) { + ?> +
    + + + + + section as $section) { + ?> +
    + + + + + + + + + + + + +?> + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php new file mode 100644 index 000000000..f8cf4cc79 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EmbeddedPhpUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 12 => 1, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 3, + 24 => 1, + 26 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 36 => 1, + 40 => 1, + 41 => 1, + 44 => 1, + 45 => 1, + 49 => 1, + 59 => 1, + 63 => 1, + 93 => 1, + 94 => 2, + 100 => 1, + 102 => 1, + 112 => 1, + 113 => 1, + 116 => 1, + 117 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc new file mode 100644 index 000000000..ee4c73e5f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc @@ -0,0 +1,5 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php new file mode 100644 index 000000000..adee78826 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EvalUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc new file mode 100644 index 000000000..4b2a21094 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc @@ -0,0 +1,13 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php new file mode 100644 index 000000000..52f6a00a5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class GlobalKeywordUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 9 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc new file mode 100644 index 000000000..56f4393ae --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc @@ -0,0 +1,27 @@ +foo. +Now, I am printing some {$foo->bar[1]}. +This should not print a capital 'A': \x41 +EOT; + +// The following function has a simulated git conflict for testing. +// This is not a merge conflict - it is a valid test case. +// Please do not remove. +function test() + { + $arr = array( + 'a' => 'a' +<<<<<<< HEAD + 'b' => 'b' +======= + 'c' => 'c' +>>>>>>> master + ); + } diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php new file mode 100644 index 000000000..2f06f0b08 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class HeredocUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc new file mode 100644 index 000000000..dd851461b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc @@ -0,0 +1,50 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class InnerFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 46 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc new file mode 100644 index 000000000..c67381ad8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc @@ -0,0 +1,43 @@ +Count(); +$count = $object::Count(); +$count = $object->count(); +$count = $object::count(); +class MyClass { + public function Count() {} +} + +function &Sort() { + +} + +$connection = new Db\Adapter\Pdo\Mysql($config); + +namespace Strtolower\Silly; + +use function strToUpper as somethingElse; +use function MyClass\WordsToUpper as UCWords; // Intentional redeclared function error. +use function strToUpper\NotTheFunction; + +class ArrayUnique {} + +$sillyComments = strToLower /*comment*/ ($string); + +$callToGlobalFunction = \STR_REPEAT($a, 2); +$callToGlobalFunction = \ /*comment*/ str_Repeat($a, 2); + +$callToNamespacedFunction = MyNamespace /* phpcs:ignore Standard */ \STR_REPEAT($a, 2); +$callToNamespacedFunction = namespace\STR_REPEAT($a, 2); // Could potentially be false negative. + +$filePath = new \File($path); + +$count = $object?->Count(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed new file mode 100644 index 000000000..40507c040 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed @@ -0,0 +1,43 @@ +Count(); +$count = $object::Count(); +$count = $object->count(); +$count = $object::count(); +class MyClass { + public function Count() {} +} + +function &Sort() { + +} + +$connection = new Db\Adapter\Pdo\Mysql($config); + +namespace Strtolower\Silly; + +use function strtoupper as somethingElse; +use function MyClass\WordsToUpper as UCWords; // Intentional redeclared function error. +use function strToUpper\NotTheFunction; + +class ArrayUnique {} + +$sillyComments = strtolower /*comment*/ ($string); + +$callToGlobalFunction = \str_repeat($a, 2); +$callToGlobalFunction = \ /*comment*/ str_repeat($a, 2); + +$callToNamespacedFunction = MyNamespace /* phpcs:ignore Standard */ \STR_REPEAT($a, 2); +$callToNamespacedFunction = namespace\STR_REPEAT($a, 2); // Could potentially be false negative. + +$filePath = new \File($path); + +$count = $object?->Count(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php new file mode 100644 index 000000000..708d01ef0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LowercasePHPFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 27 => 1, + 33 => 1, + 35 => 1, + 36 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc new file mode 100644 index 000000000..ed7f01151 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc @@ -0,0 +1,301 @@ +{$action . 'JsonAction'}(); +} + +switch (true) { + case 1: + return foo( + function () { + $foo = $bar; // when this is removed it works ok + return false; // from here on it reports unreachable + } + ); +} + +for($i=0,$j=50; $i<100; $i++) { + while($j--) { + if($j==17) { + goto end; + echo 'unreachable'; + } + } +} + +switch ($var) { + case '1': + goto end; + echo 'hi'; + + case '2': + case '3': + if ($something === true) { + goto end; + echo 'hi'; + } + break; + default: + goto end; + + if ($something === true) { + goto end; + echo 'hi'; + } +} + +end: +echo 'j hit 17'; + +// Issue 2512. +class TestAlternativeControlStructures { + + public function alternative_switch_in_function( $var ) { + + switch ( $var ) : + case 'value1': + do_something(); + break; + + default: + case 'value2': + do_something_else(); + break; + endswitch; + } + + public function various_alternative_control_structures() { + $_while = 1; + + for ( $a = 0; $a++ < 1; ) : + foreach ( [ 1 ] as $b ) : + while ( $_while-- ) : + if ( 1 ) : + switch ( 1 ) : + default: + echo 'yay, we made it!'; + break; + endswitch; + endif; + endwhile; + endforeach; + endfor; + } +} + +$var_after_class_in_global_space = 1; +do_something_else(); + +// Intentional syntax error. +return array_map( diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc new file mode 100644 index 000000000..c9bf052f3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class NonExecutableCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'NonExecutableCodeUnitTest.1.inc': + return [ + 5 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 19 => 2, + 28 => 1, + 32 => 1, + 33 => 2, + 34 => 2, + 42 => 1, + 45 => 1, + 54 => 1, + 58 => 1, + 73 => 1, + 83 => 1, + 95 => 1, + 105 => 1, + 123 => 1, + 147 => 1, + 150 => 1, + 153 => 1, + 166 => 1, + 180 => 1, + 232 => 1, + 240 => 1, + 246 => 1, + 252 => 1, + 253 => 1, + 254 => 2, + ]; + break; + case 'NonExecutableCodeUnitTest.2.inc': + return [ + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 2, + 14 => 1, + 54 => 2, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc new file mode 100644 index 000000000..6df12cca4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MemberVarScopeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 25 => 1, + 29 => 1, + 33 => 1, + 39 => 1, + 41 => 1, + 66 => 2, + 67 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [71 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc new file mode 100644 index 000000000..3cc617d75 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MethodScopeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 30 => 1, + 39 => 1, + 46 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc new file mode 100644 index 000000000..dd6530e80 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc @@ -0,0 +1,127 @@ +func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + public static function /* */ func1() + { + return $this->setValue($result); + } + + public static function + func1() + { + return $this->setValue($result); + } + + public function func1() + { + $value = 'hello'; + $newValue = array($this->func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + function func1() + { + $value = 'hello'; + $newValue = array($this->func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + public static function func1() { + return function() { + echo $this->name; + }; + } + + private static function func1(array $data) + { + return new class() + { + private $data; + + public function __construct(array $data) + { + $this->data = $data; + } + }; + } + + public function getAnonymousClass() { + return new class() { + public static function something() { + $this->doSomething(); + } + }; + } +} + +trait MyTrait { + public static function myFunc() { + $this->doSomething(); + } +} + +$b = new class() +{ + public static function myFunc() { + $this->doSomething(); + } + + public static function other() { + return fn () => $this->name; + } + + public static function anonClassUseThis() { + return new class($this) { + public function __construct($class) { + } + }; + } + + public static function anonClassAnotherThis() { + return new class() { + public function __construct() { + $this->id = 1; + } + }; + } + + public static function anonClassNestedUseThis() { + return new class(new class($this) {}) { + }; + } + + public static function anonClassNestedAnotherThis() { + return new class(new class() { + public function __construct() { + $this->id = 1; + } + }) { + }; + } + + public static function thisMustBeLowercase() { + $This = 'hey'; + + return $This; + } +} + +enum MyEnum { + private function notStatic () { + $this->doSomething(); + } + + public static function myFunc() { + $this->doSomething(); + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php new file mode 100644 index 000000000..b1a5dd6af --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class StaticThisUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 8 => 1, + 9 => 1, + 14 => 1, + 20 => 1, + 41 => 1, + 61 => 1, + 69 => 1, + 76 => 1, + 80 => 1, + 84 => 1, + 99 => 1, + 125 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc new file mode 100644 index 000000000..3bf4186e0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc @@ -0,0 +1,49 @@ +add_help_tab( array( +'id' => <<', +) ); + +// phpcs:set Squiz.Strings.ConcatenationSpacing spacing 1 + +$string = 'Hello'.$there.'. How are'.$you.$going. "today $okay"; +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello'.$there; +$string = 'Hello'. $there; +$string = 'Hello' .$there; + +// phpcs:set Squiz.Strings.ConcatenationSpacing ignoreNewlines true +$y = '1' + . '2' + . '3'; + +$y = '1' . + '2' . + '3'; + +$y = '1' +. '2' +. '3'; + +$y = '1' + .'2'. + '3' + . '4'; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..b45f1a43a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed @@ -0,0 +1,47 @@ +add_help_tab( array( +'id' => <<', +) ); + +// phpcs:set Squiz.Strings.ConcatenationSpacing spacing 1 + +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello' . $there; +$string = 'Hello' . $there; +$string = 'Hello' . $there; + +// phpcs:set Squiz.Strings.ConcatenationSpacing ignoreNewlines true +$y = '1' + . '2' + . '3'; + +$y = '1' . + '2' . + '3'; + +$y = '1' +. '2' +. '3'; + +$y = '1' + . '2' . + '3' + . '4'; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php new file mode 100644 index 000000000..862af7d20 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ConcatenationSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 5, + 5 => 1, + 6 => 1, + 9 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 5, + 22 => 1, + 27 => 5, + 29 => 1, + 30 => 1, + 31 => 1, + 47 => 2, + 49 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc new file mode 100644 index 000000000..c8cc63836 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc @@ -0,0 +1,37 @@ +"; +$string = "Value: $var[test]"; +$string = "\0"; +$string = "\$var"; + +$x = "bar = '$z', +baz = '" . $a . "'...$x"; + +$string = "Hello +there"; +$string = 'Hello +there'; + +$string = "\123 \234"."\u123"."\e"; + +echo "window.location = \"".$url."\";\n"; +echo "" + +$string = "Hello + there"; + +function test() { + echo "It Worked'; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed new file mode 100644 index 000000000..97309194e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed @@ -0,0 +1,37 @@ +"; +$string = "Value: $var[test]"; +$string = "\0"; +$string = '$var'; + +$x = "bar = '$z', +baz = '" . $a . "'...$x"; + +$string = 'Hello +there'; +$string = 'Hello +there'; + +$string = "\123 \234"."\u123"."\e"; + +echo 'window.location = "'.$url."\";\n"; +echo '' + +$string = 'Hello + there'; + +function test() { + echo "It Worked'; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php new file mode 100644 index 000000000..a95d1888b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class DoubleQuoteUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 8 => 2, + 14 => 1, + 15 => 1, + 17 => 1, + 19 => 1, + 20 => 1, + 22 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc new file mode 100644 index 000000000..9e0391dad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc @@ -0,0 +1,13 @@ +returndate == 0) ? 'Not returned' : date('d/m/Y', $loan_device->returndate); +?> +

    +

    diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed new file mode 100644 index 000000000..37c7d24c3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed @@ -0,0 +1,13 @@ +returndate == 0) ? 'Not returned' : date('d/m/Y', $loan_device->returndate); +?> +

    +

    diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php new file mode 100644 index 000000000..0d9af1e93 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class EchoedStringsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc new file mode 100644 index 000000000..fa65112fb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class CastSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 9 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc new file mode 100644 index 000000000..70abae434 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,269 @@ + +
    + + + +
    + children as $child) { + // There should be no error after this + // foreach, because it is followed by a + // close PHP tag. + } + ?> +
    +children as $child) { + echo $child; + +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +foreach ( $blah as $var ) { + if ( $blah ) { + } +} + +if ( + $defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +$moo = 'blar'; +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; + + default: + $moo = 'moo'; + break; +} + +do { +} +while (true); + +try { + // Something +} catch (Exception $e) { + // Something +} + +try { + + // Something + +} catch (Exception $e) { + + // Something + +} + +if ($one) { +} +elseif ($two) { +} +// else if something +else if ($three) { +} // else do something +else { +} + +if ($one) { + +} + +do { + echo 'hi'; +} while ( $blah ); + +if ($one) { +} +// No blank line here. +if ($two) { +} + +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + + return $moo; +} + +try { + // Something +} +catch (Exception $e) { + // Something +} +finally { + // Something +} + +if ($foo) { + + + /** + * Comment + */ + function foo() { + // Code here + } + + + /** + * Comment + */ + class bar() { + + }//end class + + +} + +if (true) { // some comment goes here + + echo 'foo'; +} + +if (true) { echo 'foo'; + + echo 'foo'; +} + +if ($true) { + echo 'hi 2'; +}//end if +echo 'hi'; + +if ($true) { + echo 'hi 2'; +} // phpcs:enable Standard.Category.Sniff -- for reasons. +echo 'hi'; + +?> + + + + + + + 1, + 2 => 2, + +}; +echo $expr; + +if($true) { + + enum SomeEnum {} + +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..c64de25e1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,261 @@ + + + + + +
    + children as $child) { + // There should be no error after this + // foreach, because it is followed by a + // close PHP tag. + } + ?> +
    +children as $child) { + echo $child; +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +foreach ($blah as $var) { + if ($blah) { + } +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +$moo = 'blar'; +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; + + default: + $moo = 'moo'; + break; +} + +do { +} +while (true); + +try { + // Something +} catch (Exception $e) { + // Something +} + +try { + // Something +} catch (Exception $e) { + // Something +} + +if ($one) { +} +elseif ($two) { +} +// else if something +else if ($three) { +} // else do something +else { +} + +if ($one) { +} + +do { + echo 'hi'; +} while ($blah); + +if ($one) { +} + +// No blank line here. +if ($two) { +} + +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; +} + +try { + // Something +} +catch (Exception $e) { + // Something +} +finally { + // Something +} + +if ($foo) { + + + /** + * Comment + */ + function foo() { + // Code here + } + + + /** + * Comment + */ + class bar() { + + }//end class + + +} + +if (true) { // some comment goes here + echo 'foo'; +} + +if (true) { echo 'foo'; + + echo 'foo'; +} + +if ($true) { + echo 'hi 2'; +}//end if + +echo 'hi'; + +if ($true) { + echo 'hi 2'; +} // phpcs:enable Standard.Category.Sniff -- for reasons. + +echo 'hi'; + +?> + + + + + + 1, + 2 => 2, +}; + +echo $expr; + +if($true) { + + enum SomeEnum {} + +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js new file mode 100644 index 000000000..1c889a1c0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js @@ -0,0 +1,93 @@ + +if (something) { +} +for (i = 0; i < 10; i++) { +} + +while (true) { + for (i = 0; i < 10; i++) { + } + if (something) { + } + + do { + } while (true); + +} + +if (one) { +} else (two) { +} else if (three) { +} +if (one) { +} else (two) { +} else if (three) { +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // There are no spaces before break. + } + break; +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // Code here. + } +} + +for (i = 0; i < 10; i++) { + if (blah) { + } + break; +} + +while (true) { + for (i = 0; i < 10; i++) { + + if (something) { + } + + } + + do { + + alert(i); + } while (true); +} + +for ( i = 0; i < 10; i++ ) { + if ( blah ) { + } +} + +var x = { + a: function () { + if (blah) { + } + + }, +}; + +if (one) { +} +// else if something +else if (two) { +} // else do something +else { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed new file mode 100644 index 000000000..bb979bc8e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed @@ -0,0 +1,93 @@ + +if (something) { +} + +for (i = 0; i < 10; i++) { +} + +while (true) { + for (i = 0; i < 10; i++) { + } + + if (something) { + } + + do { + } while (true); +} + +if (one) { +} else (two) { +} else if (three) { +} + +if (one) { +} else (two) { +} else if (three) { +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // There are no spaces before break. + } + break; +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // Code here. + } +} + +for (i = 0; i < 10; i++) { + if (blah) { + } + + break; +} + +while (true) { + for (i = 0; i < 10; i++) { + if (something) { + } + } + + do { + alert(i); + } while (true); +} + +for (i = 0; i < 10; i++) { + if (blah) { + } +} + +var x = { + a: function () { + if (blah) { + } + + }, +}; + +if (one) { +} +// else if something +else if (two) { +} // else do something +else { +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php new file mode 100644 index 000000000..ac3f5d6ff --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='ControlStructureSpacingUnitTest.inc') + { + switch ($testFile) { + case 'ControlStructureSpacingUnitTest.inc': + return [ + 3 => 1, + 5 => 1, + 8 => 1, + 15 => 1, + 23 => 1, + 74 => 1, + 79 => 1, + 82 => 1, + 83 => 1, + 87 => 1, + 103 => 1, + 113 => 2, + 114 => 2, + 118 => 1, + 150 => 1, + 153 => 1, + 154 => 1, + 157 => 1, + 170 => 1, + 176 => 2, + 179 => 1, + 189 => 1, + 225 => 1, + 237 => 1, + 242 => 1, + 246 => 1, + 248 => 1, + 257 => 3, + 261 => 1, + 262 => 1, + ]; + break; + case 'ControlStructureSpacingUnitTest.js': + return [ + 3 => 1, + 9 => 1, + 15 => 1, + 21 => 1, + 56 => 1, + 61 => 1, + 64 => 1, + 65 => 1, + 68 => 1, + 74 => 2, + 75 => 2, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc new file mode 100644 index 000000000..e831e257d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc @@ -0,0 +1,39 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionClosingBraceSpaceUnitTest.inc') + { + switch ($testFile) { + case 'FunctionClosingBraceSpaceUnitTest.inc': + return [ + 10 => 1, + 21 => 1, + 28 => 1, + 29 => 1, + 31 => 1, + 39 => 1, + ]; + break; + case 'FunctionClosingBraceSpaceUnitTest.js': + return [ + 13 => 1, + 25 => 1, + 32 => 1, + 53 => 1, + 59 => 1, + 67 => 1, + 84 => 1, + 128 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc new file mode 100644 index 000000000..fe2c903b1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='FunctionOpeningBraceSpaceUnitTest.inc') + { + switch ($testFile) { + case 'FunctionOpeningBraceSpaceUnitTest.inc': + return [ + 10 => 1, + 25 => 1, + 49 => 1, + ]; + + case 'FunctionOpeningBraceSpaceUnitTest.js': + return [ + 11 => 1, + 31 => 1, + 38 => 1, + 88 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc new file mode 100644 index 000000000..36a287f07 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc @@ -0,0 +1,576 @@ +setLogger(new class { + public function a(){} + private function b(){} + protected function c(){} +}); + +?> + +setLogger(new class { + + public function a(){} + + private function b(){} + + protected function c(){} + +}); + +?> + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class FunctionSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionSpacingUnitTest.1.inc': + return [ + 26 => 1, + 35 => 1, + 44 => 1, + 51 => 1, + 55 => 1, + 61 => 1, + 64 => 1, + 66 => 1, + 81 => 1, + 100 => 1, + 111 => 1, + 113 => 1, + 119 => 2, + 141 => 1, + 160 => 1, + 173 => 2, + 190 => 1, + 224 => 2, + 281 => 1, + 282 => 1, + 295 => 1, + 297 => 1, + 303 => 1, + 327 => 1, + 329 => 1, + 338 => 1, + 344 => 1, + 345 => 1, + 354 => 2, + 355 => 1, + 356 => 1, + 360 => 2, + 361 => 1, + 362 => 1, + 385 => 1, + 399 => 1, + 411 => 2, + 418 => 2, + 426 => 2, + 432 => 1, + 437 => 1, + 438 => 1, + 442 => 2, + 444 => 1, + 449 => 1, + 458 => 2, + 459 => 1, + 460 => 1, + 465 => 2, + 466 => 1, + 467 => 1, + 471 => 1, + 473 => 2, + 475 => 1, + 478 => 2, + 479 => 1, + 483 => 2, + 495 => 1, + 529 => 1, + 539 => 1, + 547 => 2, + 551 => 1, + 553 => 1, + 560 => 1, + 566 => 1, + ]; + + case 'FunctionSpacingUnitTest.2.inc': + return [2 => 1]; + + case 'FunctionSpacingUnitTest.3.inc': + return [7 => 1]; + + case 'FunctionSpacingUnitTest.5.inc': + return [5 => 1]; + + case 'FunctionSpacingUnitTest.6.inc': + return [10 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc new file mode 100644 index 000000000..e8f2edad3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc @@ -0,0 +1,43 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 31 => 1, + 34 => 1, + 35 => 1, + 39 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc new file mode 100644 index 000000000..c2f4ec7db --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc @@ -0,0 +1,19 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class LogicalOperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='LogicalOperatorSpacingUnitTest.inc') + { + return [ + 4 => 2, + 5 => 3, + 6 => 3, + 15 => 1, + 17 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc new file mode 100644 index 000000000..12b55176c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc @@ -0,0 +1,374 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; +} + +// Make sure the determination of whether a property is the first property or not is done correctly. +class ClassUsingSimpleTraits +{ + use HelloWorld; + + + /* comment */ + public $firstVar = array( 'a', 'b' ); + protected $secondVar = true; +} + +class ClassUsingComplexTraits +{ + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } + + + + public $firstVar = array( 'a', 'b' ); + + + /* comment */ + protected $secondVar = true; +} + +class Foo +{ + + + private function foo() + { + } + + + /* no error here because after function */ + private $bar = false; +} + +class CommentedOutCodeAtStartOfClass { + + /** + * Description. + * + * @var bool + */ + //public $commented_out_property = true; + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class CommentedOutCodeAtStartOfClassNoBlankLine { + + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + + #[ORM\Id]#[ORM\Column("integer")] + + private $id; + + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; + + #[SingleAttribute] + protected $propertySingle; + + #[FirstAttribute] + #[SecondAttribute] + protected $propertyDouble; + #[ThirdAttribute] + protected $propertyWithoutSpacing; +} + +enum SomeEnum +{ + // Enum cannot have properties + + case ONE = 'one'; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..d683eaadf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed @@ -0,0 +1,359 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; +} + +// Make sure the determination of whether a property is the first property or not is done correctly. +class ClassUsingSimpleTraits +{ + use HelloWorld; + + /* comment */ + public $firstVar = array( 'a', 'b' ); + + protected $secondVar = true; +} + +class ClassUsingComplexTraits +{ + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } + + public $firstVar = array( 'a', 'b' ); + + /* comment */ + protected $secondVar = true; +} + +class Foo +{ + + + private function foo() + { + } + + + /* no error here because after function */ + private $bar = false; +} + +class CommentedOutCodeAtStartOfClass { + + /** + * Description. + * + * @var bool + */ + //public $commented_out_property = true; + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class CommentedOutCodeAtStartOfClassNoBlankLine { + + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class HasAttributes +{ + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; + + #[SingleAttribute] + protected $propertySingle; + + #[FirstAttribute] + #[SecondAttribute] + protected $propertyDouble; + + #[ThirdAttribute] + protected $propertyWithoutSpacing; +} + +enum SomeEnum +{ + // Enum cannot have properties + + case ONE = 'one'; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php new file mode 100644 index 000000000..9b4066811 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class MemberVarSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 7 => 1, + 20 => 1, + 30 => 1, + 35 => 1, + 44 => 1, + 50 => 1, + 73 => 1, + 86 => 1, + 106 => 1, + 115 => 1, + 150 => 1, + 160 => 1, + 165 => 1, + 177 => 1, + 186 => 1, + 200 => 1, + 209 => 1, + 211 => 1, + 224 => 1, + 229 => 1, + 241 => 1, + 246 => 1, + 252 => 1, + 254 => 1, + 261 => 1, + 275 => 1, + 276 => 1, + 288 => 1, + 292 => 1, + 333 => 1, + 342 => 1, + 346 => 1, + 353 => 1, + 357 => 1, + 366 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc new file mode 100644 index 000000000..67f8ee144 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc @@ -0,0 +1,52 @@ +testThis(); +$this-> testThis(); +$this -> testThis(); +$this-> /* comment here */testThis(); +$this/* comment here */ -> testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +$this->testThis(); +$this-> testThis(); +$this -> testThis(); +$this->/* comment here */testThis(); +$this/* comment here */ -> testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +thisObject::testThis(); +thisObject:: testThis(); +thisObject :: testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */ :: testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +thisObject::testThis(); +thisObject:: testThis(); +thisObject :: testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */ :: testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +$this?->testThis(); +$this?-> testThis(); +$this ?-> testThis(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..730b8e4a7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,48 @@ +testThis(); +$this->testThis(); +$this->testThis(); +$this->/* comment here */testThis(); +$this/* comment here */->testThis(); +$this->testThis(); +$this->testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +$this->testThis(); +$this->testThis(); +$this->testThis(); +$this->/* comment here */testThis(); +$this/* comment here */->testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +thisObject::testThis(); +thisObject::testThis(); +thisObject::testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */::testThis(); +thisObject::testThis(); +thisObject::testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +thisObject::testThis(); +thisObject::testThis(); +thisObject::testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */::testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +$this?->testThis(); +$this?->testThis(); +$this?->testThis(); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php new file mode 100644 index 000000000..82a4056f7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ObjectOperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 2, + 5 => 1, + 6 => 2, + 8 => 1, + 9 => 1, + 15 => 1, + 16 => 2, + 18 => 2, + 27 => 1, + 28 => 2, + 30 => 2, + 32 => 1, + 33 => 1, + 39 => 1, + 40 => 2, + 42 => 2, + 51 => 1, + 52 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc new file mode 100644 index 000000000..f89cf08d5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc @@ -0,0 +1,481 @@ + $j && $k< $l && $m>= $n && $o<= $p && $q<> $r; + +$a ==$b && $c !=$d && $e ===$f && $g !==$h; +$i >$j && $k <$l && $m >=$n && $o <=$p && $q <>$r; + +function myFunction($variable=0, $var2='string') {} + +if (index > -1) { +} + +array_walk_recursive($array, function(&$item) use (&$something) { +}); + +$var = saveFile(&$model, &$foo); + +// This is all valid. +$boo = -$foo; +function foo($boo = -1) {} +$foo = array('boo' => -1); +$x = $test ? -1 : 1; +$y = $test ? 1 : -1; +$z = $test ?: false; + +$closureWithDefaultParameter = function (array $testArray=array()) {}; + +switch ($foo) { + case -1: + break; +} + +$y = 1 * -1; +$y = -1 * 1; +$y = -1 * $var; +$y = 10 / -2; +$y = -10 / 2; +$y = (-10 / 2); +$y = (-10 / $var); +$y = 10 + -2; +$y = -10 + 2; + +$a = $x?$y:$z; +$a = $x ? $y : $z; + +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == $b) { +} + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$y = array(&$x); +$y = [&$x]; +$y = array(&$a, &$b, &$c); +$y = [&$a, &$b, &$c]; +$y = array(&$a => 1, 2 => &$b, &$c); +$y = [&$a => 1, 2 => &$b, &$c]; + +if ($a <=> $b) { +} + +if ($a <=>$b) { +} + +$a |= $b; +$a **= $b; +$a ??= $b; + +$a = +1; + +function bar($boo = +1) {} + +$username = $_GET['user']??'nobody'; + +function foo(string $bar, array $baz, ?MyClass $object) : MyClass {} + +declare(strict_types=1); + +function foo($c = ((BAR)?10:100)) {} + +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; + +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; + +function foo(string $a = '', ?string $b = ''): ?string {} + +// Issue #1605. +$text = preg_replace_callback( + self::CHAR_REFS_REGEX, + [ 'Sanitizer', 'decodeCharReferencesCallback' ], + $text, /* limit */ -1, $count ); + +if (true || /* test */ -1 == $b) {} +$y = 10 + /* test */ -2; + +// Issue #1604. +Hooks::run( 'ParserOptionsRegister', [ + &self::$defaults, + &self::$inCacheKey, + &self::$lazyOptions, +] ); + +$x = $foo ? function (): int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) + // comment + : int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) use /* comment */ ($bar): int { + return 1; +} : $bar; + +$x = !$foo ? $bar : function (): int { + return 1; +}; + +$a = + // Comment. + [ + 'a', + 'b', + ]; + +$a = +// phpcs:ignore Standard.Category.Sniff -- for reasons. +[ + 'a', + 'b', +]; + +$foo = is_array($bar) ? array_map( + function () {}, + $bar + ) : $bar; + +function bar(): array {} + +if ($line{-1} === ':') { + $line = substr($line, 0, -1); +} + +$a = $a instanceof $b; +$a = $a instanceof $b; +$a = ($a)instanceof$b; + +fn&($x) => $x; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +$a = 3; + +yield -1; +echo -1; +$a = -1; +func(-1); +$a = [-1]; +return -1; +print -1; +$a &= -1; +switch ($a) { + case -1: +} +$a = $a ?? -1; +$a .= -1; +$a /= -1; +$a = [1 => -1]; +$a = $a == -1; +$a = $a >= -1; +$a = $a === -1; +$a = $a != -1; +$a = $a !== -1; +$a = $a <= -1; +$a = $a <=> -1; +$a = $a and -1; +$a = $a or -1; +$a = $a xor -1; +$a -= -1; +$a %= -1; +$a *= -1; +$a |= -1; +$a += -1; +$a = $a ** -1; +$a **= -1; +$a = $a << -1; +$a <<= -1; +$a = $a >> -1; +$a >>= -1; +$a = (string) -1; +$a = (array) -1; +$a = (bool) -1; +$a = (object) -1; +$a = (unset) -1; +$a = (float) -1; +$a = (int) -1; +$a ^= -1; +$a = [$a, -1]; +$a = $a[-1]; +$a = $a ? -1 : -1; + +yield - 1; +echo - 1; +$a = - 1; +func(- 1); +$a = [- 1]; +return - 1; +print - 1; +$a &= - 1; +switch ($a) { + case - 1: +} +$a = $a ?? - 1; +$a .= - 1; +$a /= - 1; +$a = [1 => - 1]; +$a = $a == - 1; +$a = $a >= - 1; +$a = $a === - 1; +$a = $a != - 1; +$a = $a !== - 1; +$a = $a <= - 1; +$a = $a <=> - 1; +$a = $a and - 1; +$a = $a or - 1; +$a = $a xor - 1; +$a -= - 1; +$a %= - 1; +$a *= - 1; +$a |= - 1; +$a += - 1; +$a = $a ** - 1; +$a **= - 1; +$a = $a << - 1; +$a <<= - 1; +$a = $a >> - 1; +$a >>= - 1; +$a = (string) - 1; +$a = (array) - 1; +$a = (bool) - 1; +$a = (object) - 1; +$a = (unset) - 1; +$a = (float) - 1; +$a = (int) - 1; +$a ^= - 1; +$a = [$a, - 1]; +$a = $a[- 1]; +$a = $a ? - 1 : - 1; + + +yield -$b; +echo -$b; +$a = -$b; +func(-$b); +$a = [-$b]; +return -$b; +print -$b; +$a &= -$b; +switch ($a) { + case -$b: +} +$a = $a ?? -$b; +$a .= -$b; +$a /= -$b; +$a = [1 => -$b]; +$a = $a == -$b; +$a = $a >= -$b; +$a = $a === -$b; +$a = $a != -$b; +$a = $a !== -$b; +$a = $a <= -$b; +$a = $a <=> -$b; +$a = $a and -$b; +$a = $a or -$b; +$a = $a xor -$b; +$a -= -$b; +$a %= -$b; +$a *= -$b; +$a |= -$b; +$a += -$b; +$a = $a ** -$b; +$a **= -$b; +$a = $a << -$b; +$a <<= -$b; +$a = $a >> -$b; +$a >>= -$b; +$a = (string) -$b; +$a = (array) -$b; +$a = (bool) -$b; +$a = (object) -$b; +$a = (unset) -$b; +$a = (float) -$b; +$a = (int) -$b; +$a ^= -$b; +$a = [$a, -$b]; +$a = $a[-$b]; +$a = $a ? -$b : -$b; + +yield - $b; +echo - $b; +$a = - $b; +func(- $b); +$a = [- $b]; +return - $b; +print - $b; +$a &= - $b; +switch ($a) { + case - $b: +} +$a = $a ?? - $b; +$a .= - $b; +$a /= - $b; +$a = [1 => - $b]; +$a = $a == - $b; +$a = $a >= - $b; +$a = $a === - $b; +$a = $a != - $b; +$a = $a !== - $b; +$a = $a <= - $b; +$a = $a <=> - $b; +$a = $a and - $b; +$a = $a or - $b; +$a = $a xor - $b; +$a -= - $b; +$a %= - $b; +$a *= - $b; +$a |= - $b; +$a += - $b; +$a = $a ** - $b; +$a **= - $b; +$a = $a << - $b; +$a <<= - $b; +$a = $a >> - $b; +$a >>= - $b; +$a = (string) - $b; +$a = (array) - $b; +$a = (bool) - $b; +$a = (object) - $b; +$a = (unset) - $b; +$a = (float) - $b; +$a = (int) - $b; +$a ^= - $b; +$a = [$a, - $b]; +$a = $a[- $b]; +$a = $a ? - $b : - $b; + +exit -1; + +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +$a = 'a '.-MY_CONSTANT; +$a = 'a '.-$b; +$a = 'a '.- MY_CONSTANT; +$a = 'a '.- $b; + +/* Intentional parse error. This has to be the last test in the file. */ +$a = 10 + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..138616e75 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,475 @@ + $j && $k < $l && $m >= $n && $o <= $p && $q <> $r; + +$a == $b && $c != $d && $e === $f && $g !== $h; +$i > $j && $k < $l && $m >= $n && $o <= $p && $q <> $r; + +function myFunction($variable=0, $var2='string') {} + +if (index > -1) { +} + +array_walk_recursive($array, function(&$item) use (&$something) { +}); + +$var = saveFile(&$model, &$foo); + +// This is all valid. +$boo = -$foo; +function foo($boo = -1) {} +$foo = array('boo' => -1); +$x = $test ? -1 : 1; +$y = $test ? 1 : -1; +$z = $test ?: false; + +$closureWithDefaultParameter = function (array $testArray=array()) {}; + +switch ($foo) { + case -1: + break; +} + +$y = 1 * -1; +$y = -1 * 1; +$y = -1 * $var; +$y = 10 / -2; +$y = -10 / 2; +$y = (-10 / 2); +$y = (-10 / $var); +$y = 10 + -2; +$y = -10 + 2; + +$a = $x ? $y : $z; +$a = $x ? $y : $z; + +$y = 1 + 2 - 3; + +$y = 1 + 2 - 3; + +$y = 1 + 2 - 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == $b) { +} + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$y = array(&$x); +$y = [&$x]; +$y = array(&$a, &$b, &$c); +$y = [&$a, &$b, &$c]; +$y = array(&$a => 1, 2 => &$b, &$c); +$y = [&$a => 1, 2 => &$b, &$c]; + +if ($a <=> $b) { +} + +if ($a <=> $b) { +} + +$a |= $b; +$a **= $b; +$a ??= $b; + +$a = +1; + +function bar($boo = +1) {} + +$username = $_GET['user'] ?? 'nobody'; + +function foo(string $bar, array $baz, ?MyClass $object) : MyClass {} + +declare(strict_types=1); + +function foo($c = ((BAR) ? 10 : 100)) {} + +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; + +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; + +function foo(string $a = '', ?string $b = ''): ?string {} + +// Issue #1605. +$text = preg_replace_callback( + self::CHAR_REFS_REGEX, + [ 'Sanitizer', 'decodeCharReferencesCallback' ], + $text, /* limit */ -1, $count ); + +if (true || /* test */ -1 == $b) {} +$y = 10 + /* test */ -2; + +// Issue #1604. +Hooks::run( 'ParserOptionsRegister', [ + &self::$defaults, + &self::$inCacheKey, + &self::$lazyOptions, +] ); + +$x = $foo ? function (): int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) + // comment + : int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) use /* comment */ ($bar): int { + return 1; +} : $bar; + +$x = !$foo ? $bar : function (): int { + return 1; +}; + +$a = + // Comment. + [ + 'a', + 'b', + ]; + +$a = +// phpcs:ignore Standard.Category.Sniff -- for reasons. +[ + 'a', + 'b', +]; + +$foo = is_array($bar) ? array_map( + function () {}, + $bar + ) : $bar; + +function bar(): array {} + +if ($line{-1} === ':') { + $line = substr($line, 0, -1); +} + +$a = $a instanceof $b; +$a = $a instanceof $b; +$a = ($a) instanceof $b; + +fn&($x) => $x; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +$a = 3; + +yield -1; +echo -1; +$a = -1; +func(-1); +$a = [-1]; +return -1; +print -1; +$a &= -1; +switch ($a) { + case -1: +} +$a = $a ?? -1; +$a .= -1; +$a /= -1; +$a = [1 => -1]; +$a = $a == -1; +$a = $a >= -1; +$a = $a === -1; +$a = $a != -1; +$a = $a !== -1; +$a = $a <= -1; +$a = $a <=> -1; +$a = $a and -1; +$a = $a or -1; +$a = $a xor -1; +$a -= -1; +$a %= -1; +$a *= -1; +$a |= -1; +$a += -1; +$a = $a ** -1; +$a **= -1; +$a = $a << -1; +$a <<= -1; +$a = $a >> -1; +$a >>= -1; +$a = (string) -1; +$a = (array) -1; +$a = (bool) -1; +$a = (object) -1; +$a = (unset) -1; +$a = (float) -1; +$a = (int) -1; +$a ^= -1; +$a = [$a, -1]; +$a = $a[-1]; +$a = $a ? -1 : -1; + +yield - 1; +echo - 1; +$a = - 1; +func(- 1); +$a = [- 1]; +return - 1; +print - 1; +$a &= - 1; +switch ($a) { + case - 1: +} +$a = $a ?? - 1; +$a .= - 1; +$a /= - 1; +$a = [1 => - 1]; +$a = $a == - 1; +$a = $a >= - 1; +$a = $a === - 1; +$a = $a != - 1; +$a = $a !== - 1; +$a = $a <= - 1; +$a = $a <=> - 1; +$a = $a and - 1; +$a = $a or - 1; +$a = $a xor - 1; +$a -= - 1; +$a %= - 1; +$a *= - 1; +$a |= - 1; +$a += - 1; +$a = $a ** - 1; +$a **= - 1; +$a = $a << - 1; +$a <<= - 1; +$a = $a >> - 1; +$a >>= - 1; +$a = (string) - 1; +$a = (array) - 1; +$a = (bool) - 1; +$a = (object) - 1; +$a = (unset) - 1; +$a = (float) - 1; +$a = (int) - 1; +$a ^= - 1; +$a = [$a, - 1]; +$a = $a[- 1]; +$a = $a ? - 1 : - 1; + + +yield -$b; +echo -$b; +$a = -$b; +func(-$b); +$a = [-$b]; +return -$b; +print -$b; +$a &= -$b; +switch ($a) { + case -$b: +} +$a = $a ?? -$b; +$a .= -$b; +$a /= -$b; +$a = [1 => -$b]; +$a = $a == -$b; +$a = $a >= -$b; +$a = $a === -$b; +$a = $a != -$b; +$a = $a !== -$b; +$a = $a <= -$b; +$a = $a <=> -$b; +$a = $a and -$b; +$a = $a or -$b; +$a = $a xor -$b; +$a -= -$b; +$a %= -$b; +$a *= -$b; +$a |= -$b; +$a += -$b; +$a = $a ** -$b; +$a **= -$b; +$a = $a << -$b; +$a <<= -$b; +$a = $a >> -$b; +$a >>= -$b; +$a = (string) -$b; +$a = (array) -$b; +$a = (bool) -$b; +$a = (object) -$b; +$a = (unset) -$b; +$a = (float) -$b; +$a = (int) -$b; +$a ^= -$b; +$a = [$a, -$b]; +$a = $a[-$b]; +$a = $a ? -$b : -$b; + +yield - $b; +echo - $b; +$a = - $b; +func(- $b); +$a = [- $b]; +return - $b; +print - $b; +$a &= - $b; +switch ($a) { + case - $b: +} +$a = $a ?? - $b; +$a .= - $b; +$a /= - $b; +$a = [1 => - $b]; +$a = $a == - $b; +$a = $a >= - $b; +$a = $a === - $b; +$a = $a != - $b; +$a = $a !== - $b; +$a = $a <= - $b; +$a = $a <=> - $b; +$a = $a and - $b; +$a = $a or - $b; +$a = $a xor - $b; +$a -= - $b; +$a %= - $b; +$a *= - $b; +$a |= - $b; +$a += - $b; +$a = $a ** - $b; +$a **= - $b; +$a = $a << - $b; +$a <<= - $b; +$a = $a >> - $b; +$a >>= - $b; +$a = (string) - $b; +$a = (array) - $b; +$a = (bool) - $b; +$a = (object) - $b; +$a = (unset) - $b; +$a = (float) - $b; +$a = (int) - $b; +$a ^= - $b; +$a = [$a, - $b]; +$a = $a[- $b]; +$a = $a ? - $b : - $b; + +exit -1; + +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +$a = 'a '.-MY_CONSTANT; +$a = 'a '.-$b; +$a = 'a '.- MY_CONSTANT; +$a = 'a '.- $b; + +/* Intentional parse error. This has to be the last test in the file. */ +$a = 10 + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js new file mode 100644 index 000000000..16eb130f5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js @@ -0,0 +1,103 @@ + + +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 +2; +result = 1+ 2; +result = 1+2; + +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 -2; +result = 1- 2; +result = 1-2; + +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 *2; +result = 1* 2; +result = 1*2; + +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 /2; +result = 1/ 2; +result = 1/2; + +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 %2; +result = 1% 2; +result = 1%2; +result = '100%'; + +result += 4; +result+=4; +result -= 4; +result-=4; +result /= 4; +result/=4; +result *=4; +result*=4; + +$.localScroll({offset: {top: -32}}); + +switch (result) { + case -1: + break; +} + +result = x?y:z; +result = x ? y : z; + +if (something === true + ^ somethingElse === true +) { + return false; +} + +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == b) { +} + +x = x << y; +x <<= y; +x = x >> y; +x >>= y; +x = x >>> y; +x >>>= y; + +var foo = bar.map(baz=> baz.length); + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +a = 3; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed new file mode 100644 index 000000000..877db4678 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed @@ -0,0 +1,97 @@ + + +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; + +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; + +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; + +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; + +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = '100%'; + +result += 4; +result += 4; +result -= 4; +result -= 4; +result /= 4; +result /= 4; +result *= 4; +result *= 4; + +$.localScroll({offset: {top: -32}}); + +switch (result) { + case -1: + break; +} + +result = x ? y : z; +result = x ? y : z; + +if (something === true + ^ somethingElse === true +) { + return false; +} + +y = 1 + 2 - 3; + +y = 1 + 2 - 3; + +y = 1 + 2 - 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == b) { +} + +x = x << y; +x <<= y; +x = x >> y; +x >>= y; +x = x >>> y; +x >>>= y; + +var foo = bar.map(baz => baz.length); + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +a = 3; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php new file mode 100644 index 000000000..8e8ad98d0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php @@ -0,0 +1,170 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class OperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='OperatorSpacingUnitTest.inc') + { + switch ($testFile) { + case 'OperatorSpacingUnitTest.inc': + return [ + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 8 => 2, + 11 => 1, + 12 => 2, + 13 => 1, + 14 => 1, + 15 => 2, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 2, + 25 => 1, + 26 => 2, + 27 => 1, + 28 => 1, + 29 => 2, + 32 => 1, + 33 => 2, + 34 => 1, + 35 => 1, + 36 => 2, + 40 => 2, + 42 => 2, + 44 => 2, + 45 => 1, + 46 => 2, + 53 => 4, + 54 => 3, + 59 => 10, + 64 => 1, + 77 => 4, + 78 => 1, + 79 => 1, + 80 => 2, + 81 => 1, + 84 => 6, + 85 => 6, + 87 => 4, + 88 => 5, + 90 => 4, + 91 => 5, + 128 => 4, + 132 => 1, + 133 => 1, + 135 => 1, + 136 => 1, + 140 => 1, + 141 => 1, + 174 => 1, + 177 => 1, + 178 => 1, + 179 => 1, + 185 => 2, + 191 => 4, + 194 => 1, + 195 => 1, + 196 => 2, + 199 => 1, + 200 => 1, + 201 => 2, + 239 => 1, + 246 => 1, + 265 => 2, + 266 => 2, + 271 => 2, + ]; + break; + case 'OperatorSpacingUnitTest.js': + return [ + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 8 => 2, + 11 => 1, + 12 => 2, + 13 => 1, + 14 => 1, + 15 => 2, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 2, + 25 => 1, + 26 => 2, + 27 => 1, + 28 => 1, + 29 => 2, + 32 => 1, + 33 => 2, + 34 => 1, + 35 => 1, + 36 => 2, + 40 => 2, + 42 => 2, + 44 => 2, + 45 => 1, + 46 => 2, + 55 => 4, + 65 => 1, + 66 => 1, + 68 => 1, + 69 => 1, + 73 => 1, + 74 => 1, + 100 => 1, + 103 => 2, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js new file mode 100644 index 000000000..15890b96a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js @@ -0,0 +1,40 @@ +var x = { + b: 'x', + xasd: x, + abc:x, + a: function () { + alert('thats right'); + x = (x?a:x); + }, + casdasd : 123123, + omgwtfbbq: { + a: 1, + b: 2 + } +}; + +id = id.replace(/row\/:/gi, ''); + +outer_loop: +for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break outer_loop; + } +} +alert('hi'); + +even_number: if ((i % 2) == 0) { + if (i == 12) + break even_number; +} + +switch (blah) { + case dfx.DOM_VK_LEFT: + this.caretLeft(shiftKey); + break; + default: + if (blah) { + } + break; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed new file mode 100644 index 000000000..f332878e6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed @@ -0,0 +1,39 @@ +var x = { + b: 'x', + xasd: x, + abc: x, + a: function () { + alert('thats right'); + x = (x?a:x); + }, + casdasd: 123123, + omgwtfbbq: { + a: 1, + b: 2 + } +}; + +id = id.replace(/row\/:/gi, ''); + +outer_loop: for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break outer_loop; + } +} +alert('hi'); + +even_number: if ((i % 2) == 0) { + if (i == 12) + break even_number; +} + +switch (blah) { + case dfx.DOM_VK_LEFT: + this.caretLeft(shiftKey); + break; + default: + if (blah) { + } + break; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php new file mode 100644 index 000000000..e80f93670 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class PropertyLabelSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 9 => 2, + 10 => 1, + 12 => 1, + 18 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc new file mode 100644 index 000000000..ecae5c6d5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc @@ -0,0 +1,134 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content']{0} === '#') +) { +} + +switch ($blah) { + case 'one': + echo 'one'; + break; + default: + echo 'another'; +} + +?> + +getRow()): ?> +

    + + + +
    + +

    o hai!

    + +
    + + + + + + + + + + + + $x + $y; + +$match = match ($test) { 1 => 'a', 2 => 'b' }; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' + }; + +?> + +
    + +
    + +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content']{0} === '#') +) { +} + +switch ($blah) { + case 'one': + echo 'one'; + break; + default: + echo 'another'; +} + +?> + +getRow()): ?> +

    + + + +
    + +

    o hai!

    + +
    + + + + + + + + + + + + $x + $y; + +$match = match ($test) { 1 => 'a', 2 => 'b' +}; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' +}; + +?> + +
    + +
    + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 13 => 1, + 24 => 1, + 80 => 1, + 102 => 1, + 111 => 1, + 116 => 1, + 122 => 1, + 130 => 1, + 134 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc new file mode 100644 index 000000000..12685dc97 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc @@ -0,0 +1,141 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; + + // Intentionally missing a semi-colon for testing. + public + $varS, + $varT +} + +// Issue #3188 - static as return type. +public static function fCreate($attributes = []): static +{ + return static::factory()->create($attributes); +} + +public static function fCreate($attributes = []): ?static +{ + return static::factory()->create($attributes); +} + +// Also account for static used within union types. +public function fCreate($attributes = []): object|static +{ +} + +// Ensure that static as a scope keyword when preceeded by a colon which is not for a type declaration is still handled. +$callback = $cond ? get_fn_name() : static function ($a) { return $a * 10; }; + +class TypedProperties { + public + int $var; + + protected string $stringA, $stringB; + + private bool + $boolA, + $boolB; +} + +// PHP 8.0 constructor property promotion. +class ConstructorPropertyPromotionTest { + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + $normalParam, + ) {} +} + +class ConstructorPropertyPromotionWithTypesTest { + public function __construct(protected float|int $x, public?string &$y = 'test', private mixed $z) {} +} + +// PHP 8.1 readonly keywords. +class ReadonlyTest { + public readonly int $publicReadonlyProperty; + + protected readonly int $protectedReadonlyProperty; + + readonly protected int $protectedReadonlyProperty; + + readonly private int $privateReadonlyProperty; + + public function __construct(readonly protected float|int $x, public readonly?string &$y = 'test') {} +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..d3b682ed7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc.fixed @@ -0,0 +1,135 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; + + // Intentionally missing a semi-colon for testing. + public + $varS, + $varT +} + +// Issue #3188 - static as return type. +public static function fCreate($attributes = []): static +{ + return static::factory()->create($attributes); +} + +public static function fCreate($attributes = []): ?static +{ + return static::factory()->create($attributes); +} + +// Also account for static used within union types. +public function fCreate($attributes = []): object|static +{ +} + +// Ensure that static as a scope keyword when preceeded by a colon which is not for a type declaration is still handled. +$callback = $cond ? get_fn_name() : static function ($a) { return $a * 10; }; + +class TypedProperties { + public int $var; + + protected string $stringA, $stringB; + + private bool + $boolA, + $boolB; +} + +// PHP 8.0 constructor property promotion. +class ConstructorPropertyPromotionTest { + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + $normalParam, + ) {} +} + +class ConstructorPropertyPromotionWithTypesTest { + public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {} +} + +// PHP 8.1 readonly keywords. +class ReadonlyTest { + public readonly int $publicReadonlyProperty; + + protected readonly int $protectedReadonlyProperty; + + readonly protected int $protectedReadonlyProperty; + + readonly private int $privateReadonlyProperty; + + public function __construct(readonly protected float|int $x, public readonly ?string &$y = 'test') {} +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php new file mode 100644 index 000000000..30b66215c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ScopeKeywordSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 2, + 8 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 17 => 2, + 26 => 1, + 28 => 1, + 29 => 1, + 64 => 1, + 67 => 1, + 71 => 1, + 103 => 1, + 106 => 1, + 111 => 1, + 119 => 1, + 121 => 1, + 127 => 2, + 134 => 2, + 138 => 2, + 140 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc new file mode 100644 index 000000000..393f48454 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc @@ -0,0 +1,42 @@ +testThis(); +$test = $this->testThis() ; +$test = $this->testThis() ; +for ($var = 1 ; $var < 10 ; $var++) { + echo $var ; +} +$test = $this->testThis() /* comment here */; +$test = $this->testThis() /* comment here */ ; + +$hello ='foo'; +; + +$sum = $a /* + $b */; +$sum = $a // + $b +; +$sum = $a /* + $b + + $c */ ; + +/* + * Test that the sniff does *not* throw incorrect errors for semi-colons in + * "empty" parts of a `for` control structure. + */ +for ($i = 1; ; $i++) {} +for ( ; $ptr >= 0; $ptr-- ) {} +for ( ; ; ) {} + +// But it should when the semi-colon in a `for` follows a comment (but shouldn't move the semi-colon). +for ( /* Deliberately left empty. */ ; $ptr >= 0; $ptr-- ) {} +for ( $i = 1 ; /* Deliberately left empty. */ ; $i++ ) {} + +switch ($foo) { + case 'foo': + ; + break + ; +} + +// This is an empty statement and should be ignored. +if ($foo) { +; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..0d06324de --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed @@ -0,0 +1,41 @@ +testThis(); +$test = $this->testThis(); +$test = $this->testThis(); +for ($var = 1; $var < 10; $var++) { + echo $var; +} +$test = $this->testThis(); /* comment here */ +$test = $this->testThis(); /* comment here */ + +$hello ='foo'; +; + +$sum = $a; /* + $b */ +$sum = $a; // + $b + +$sum = $a; /* + $b + + $c */ + +/* + * Test that the sniff does *not* throw incorrect errors for semi-colons in + * "empty" parts of a `for` control structure. + */ +for ($i = 1; ; $i++) {} +for ( ; $ptr >= 0; $ptr-- ) {} +for ( ; ; ) {} + +// But it should when the semi-colon in a `for` follows a comment (but shouldn't move the semi-colon). +for ( /* Deliberately left empty. */; $ptr >= 0; $ptr-- ) {} +for ( $i = 1; /* Deliberately left empty. */; $i++ ) {} + +switch ($foo) { + case 'foo': + ; + break; +} + +// This is an empty statement and should be ignored. +if ($foo) { +; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js new file mode 100644 index 000000000..3aafd6da9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js @@ -0,0 +1,25 @@ +var x = { + a: function () { + alert('thats right') ; + x = (x?a:x) ; + }, +} ; + +id = id.replace(/row\/:;/gi, ''); + +for (i=0 ; i<3 ; i++) { + for (j=0; j<5 ; j++) { + if (j==x) + break ; + } +} +alert('hi'); +; + +var sum = a /* + b */; + +var sum = a // +b +; + +var sum = a /* +b + + c */ ; diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed new file mode 100644 index 000000000..a547144de --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed @@ -0,0 +1,25 @@ +var x = { + a: function () { + alert('thats right'); + x = (x?a:x); + }, +}; + +id = id.replace(/row\/:;/gi, ''); + +for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break; + } +} +alert('hi'); +; + +var sum = a; /* + b */ + +var sum = a; // +b + + +var sum = a; /* +b + + c */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php new file mode 100644 index 000000000..72196f8e7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SemicolonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='SemicolonSpacingUnitTest.inc') + { + switch ($testFile) { + case 'SemicolonSpacingUnitTest.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 2, + 6 => 1, + 8 => 1, + 9 => 1, + 14 => 1, + 16 => 1, + 18 => 1, + 29 => 1, + 30 => 2, + 36 => 1, + ]; + break; + case 'SemicolonSpacingUnitTest.js': + return [ + 3 => 1, + 4 => 1, + 6 => 1, + 10 => 2, + 11 => 1, + 13 => 1, + 19 => 1, + 22 => 1, + 25 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css new file mode 100644 index 000000000..1dd1b6e6b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css @@ -0,0 +1,25 @@ + +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} + +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */ +.HelpWidgetType-new-bug-title{ + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed new file mode 100644 index 000000000..59ddddb08 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed @@ -0,0 +1,23 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} + +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */ +.HelpWidgetType-new-bug-title{ + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc new file mode 100644 index 000000000..f9dca29a4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc @@ -0,0 +1,74 @@ + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed new file mode 100644 index 000000000..1d764ebfa --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed @@ -0,0 +1,68 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js new file mode 100644 index 000000000..be542e776 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js @@ -0,0 +1,56 @@ + +alert('hi'); +alert('hello'); + +if (something) { + +} + + +function myFunction() +{ + alert('code here'); + + alert('code here'); + + + // Hello. + + /* + HI + */ + + +} + +function myFunction2() +{ + alert('code here'); + + + alert('code here'); + +} + +MyFunction = function() +{ + alert('code here'); + + + alert('code here'); + +}; + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed new file mode 100644 index 000000000..960111a5e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed @@ -0,0 +1,50 @@ +alert('hi'); +alert('hello'); + +if (something) { + +} + + +function myFunction() +{ + alert('code here'); + + alert('code here'); + + // Hello. + + /* + HI + */ + +} + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +MyFunction = function() +{ + alert('code here'); + + alert('code here'); + +}; + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css new file mode 100644 index 000000000..2025eeb19 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed new file mode 100644 index 000000000..2025eeb19 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc new file mode 100644 index 000000000..a6e2b8ad7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc @@ -0,0 +1,9 @@ + + +

    + +

    + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed new file mode 100644 index 000000000..78c452511 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed @@ -0,0 +1,7 @@ + +

    + +

    diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js new file mode 100644 index 000000000..7b0c8eacd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js @@ -0,0 +1 @@ +alert('hi'); \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed new file mode 100644 index 000000000..7b0c8eacd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed @@ -0,0 +1 @@ +alert('hi'); \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css new file mode 100644 index 000000000..9f794a082 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed new file mode 100644 index 000000000..2025eeb19 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc new file mode 100644 index 000000000..661ebdafd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed new file mode 100644 index 000000000..0cb97480e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js new file mode 100644 index 000000000..70f67193a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js @@ -0,0 +1 @@ +alert('hi'); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed new file mode 100644 index 000000000..70f67193a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed @@ -0,0 +1 @@ +alert('hi'); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc new file mode 100644 index 000000000..96860ffb0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed new file mode 100644 index 000000000..b26b5b2c1 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc new file mode 100644 index 000000000..4d6f06bcf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc @@ -0,0 +1,5 @@ +   +  \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed new file mode 100644 index 000000000..8ec5f30d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php new file mode 100644 index 000000000..b9ff96fbc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php @@ -0,0 +1,113 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class SuperfluousWhitespaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='SuperfluousWhitespaceUnitTest.inc') + { + switch ($testFile) { + case 'SuperfluousWhitespaceUnitTest.1.inc': + return [ + 2 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 16 => 1, + 23 => 1, + 28 => 1, + 33 => 1, + 49 => 1, + 62 => 1, + 65 => 1, + 73 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.2.inc': + return [ + 2 => 1, + 8 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.3.inc': + return [ + 6 => 1, + 10 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.4.inc': + case 'SuperfluousWhitespaceUnitTest.5.inc': + return [ + 1 => 1, + 4 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.1.js': + return [ + 1 => 1, + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 15 => 1, + 22 => 1, + 29 => 1, + 38 => 1, + 56 => 1, + ]; + break; + case 'SuperfluousWhitespaceUnitTest.1.css': + return [ + 1 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + 25 => 1, + ]; + break; + default: + return []; + break; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml new file mode 100644 index 000000000..87ab4c3e8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml @@ -0,0 +1,132 @@ + + + The Squiz coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + %2$s + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + 0 + + + error + + + + + 0 + + + error + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml new file mode 100644 index 000000000..c462b4f8b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $bar + $baz; +} + ]]> + + + $bar + 2; +} + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml new file mode 100644 index 000000000..aa60b8ab9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + + + + ?> + ]]> + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml new file mode 100644 index 000000000..5bcde4b84 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml @@ -0,0 +1,37 @@ + + + + + + + $testNumber = 1; + ]]> + + + $Test_Number = 1; + ]]> + + + + + _bar; +} + ]]> + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php new file mode 100644 index 000000000..5df4b0fc2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php @@ -0,0 +1,98 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; + +class CodeAnalyzerSniff implements Sniff +{ + + + /** + * Returns the token types that this sniff is interested in. + * + * @return int[] + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If ZendCodeAnalyzer could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $analyzerPath = Config::getExecutablePath('zend_ca'); + if ($analyzerPath === null) { + return; + } + + $fileName = $phpcsFile->getFilename(); + + // In the command, 2>&1 is important because the code analyzer sends its + // findings to stderr. $output normally contains only stdout, so using 2>&1 + // will pipe even stderr to stdout. + $cmd = Common::escapeshellcmd($analyzerPath).' '.escapeshellarg($fileName).' 2>&1'; + + // There is the possibility to pass "--ide" as an option to the analyzer. + // This would result in an output format which would be easier to parse. + // The problem here is that no cleartext error messages are returned; only + // error-code-labels. So for a start we go for cleartext output. + $exitCode = exec($cmd, $output, $retval); + + // Variable $exitCode is the last line of $output if no error occurs, on + // error it is numeric. Try to handle various error conditions and + // provide useful error reporting. + if (is_numeric($exitCode) === true && $exitCode > 0) { + if (is_array($output) === true) { + $msg = join('\n', $output); + } + + throw new RuntimeException("Failed invoking ZendCodeAnalyzer, exitcode was [$exitCode], retval was [$retval], output was [$msg]"); + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + // The first two lines of analyzer output contain + // something like this: + // > Zend Code Analyzer 1.2.2 + // > Analyzing ... + // So skip these... + $res = preg_match("/^.+\(line ([0-9]+)\):(.+)$/", $finding, $regs); + if (empty($regs) === true || $res === false) { + continue; + } + + $phpcsFile->addWarningOnLine(trim($regs[2]), $regs[1], 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php new file mode 100644 index 000000000..0ed34d13c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\Files; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class ClosingTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Find the last non-empty token. + $tokens = $phpcsFile->getTokens(); + for ($last = ($phpcsFile->numTokens - 1); $last > 0; $last--) { + if (trim($tokens[$last]['content']) !== '') { + break; + } + } + + if ($tokens[$last]['code'] === T_CLOSE_TAG) { + $error = 'A closing tag is not permitted at the end of a PHP file'; + $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($last - 1), null, true); + if ($tokens[$prev]['code'] !== T_SEMICOLON + && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET + && $tokens[$prev]['code'] !== T_OPEN_TAG + ) { + $phpcsFile->fixer->addContent($prev, ';'); + } + + $phpcsFile->fixer->endChangeset(); + } + + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'no'); + }//end if + + // Ignore the rest of the file. + return ($phpcsFile->numTokens + 1); + + }//end process() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..267cd0ad6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,196 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + return; + } + + $objOperator = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR + || $tokens[$objOperator]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Check to see if we are using a variable from an object. + $var = $phpcsFile->findNext([T_WHITESPACE], ($objOperator + 1), null, true); + if ($tokens[$var]['code'] === T_STRING) { + // Either a var name or a function call, so check for bracket. + $bracket = $phpcsFile->findNext([T_WHITESPACE], ($var + 1), null, true); + + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + $objVarName = $tokens[$var]['content']; + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $objVarName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $var, 'NotCamelCaps', $data); + } else if (preg_match('|\d|', $objVarName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$originalVarName]; + $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data); + } + }//end if + }//end if + }//end if + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $inClass = true; + } else { + $inClass = $phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + } + + if ($inClass === true) { + $varName = substr($varName, 1); + } + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$originalVarName]; + $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data); + } + + }//end processVariable() + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + // Exception encountered. + return; + } + + $public = ($memberProps['scope'] === 'public'); + + if ($public === true) { + if (substr($varName, 0, 1) === '_') { + $error = 'Public member variable "%s" must not contain a leading underscore'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); + } + } else { + if (substr($varName, 0, 1) !== '_') { + $scope = ucfirst($memberProps['scope']); + $error = '%s member variable "%s" must contain a leading underscore'; + $data = [ + $scope, + $varName, + ]; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); + } + } + + // Remove a potential underscore prefix for testing CamelCaps. + $varName = ltrim($varName, '_'); + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'MemberVarNotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Member variable "%s" contains numbers but this is discouraged'; + $data = [$varName]; + $phpcsFile->addWarning($warning, $stackPtr, 'MemberVarContainsNumbers', $data); + } + + }//end processMemberVar() + + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match_all('|[^\\\]\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + continue; + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'StringVarNotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$varName]; + $phpcsFile->addWarning($warning, $stackPtr, 'StringVarContainsNumbers', $data); + } + }//end foreach + }//end if + + }//end processVariableInString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc new file mode 100644 index 000000000..c8d0499dd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php new file mode 100644 index 000000000..efd3b900e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +class CodeAnalyzerUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return void + */ + protected function shouldSkipTest() + { + $analyzerPath = Config::getExecutablePath('zend_ca'); + if ($analyzerPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc new file mode 100644 index 000000000..7e7089dc3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc @@ -0,0 +1,12 @@ + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed new file mode 100644 index 000000000..caf3b38eb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed @@ -0,0 +1,12 @@ + + +

    + +
    diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc new file mode 100644 index 000000000..63df04d5f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc @@ -0,0 +1 @@ +add('arg'))?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed new file mode 100644 index 000000000..b4c462198 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed @@ -0,0 +1 @@ +add('arg')); diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc new file mode 100644 index 000000000..539365dad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc @@ -0,0 +1 @@ +add('arg')) /* comment */ ?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed new file mode 100644 index 000000000..4cc31a510 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed @@ -0,0 +1 @@ +add('arg')); /* comment */ diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc new file mode 100644 index 000000000..09e484407 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc @@ -0,0 +1 @@ +add('arg')); } ?> diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed new file mode 100644 index 000000000..9ff112a4c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed @@ -0,0 +1 @@ +add('arg')); } diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc new file mode 100644 index 000000000..48de7e035 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed new file mode 100644 index 000000000..796727a8f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed @@ -0,0 +1,3 @@ + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed new file mode 100644 index 000000000..dc84e23ee --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed @@ -0,0 +1 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ClosingTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingTagUnitTest.1.inc': + return [11 => 1]; + + case 'ClosingTagUnitTest.3.inc': + case 'ClosingTagUnitTest.4.inc': + case 'ClosingTagUnitTest.5.inc': + case 'ClosingTagUnitTest.7.inc': + return [1 => 1]; + + case 'ClosingTagUnitTest.6.inc': + return [3 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 000000000..3325e1152 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,131 @@ +varName; +echo $this->var_name; +echo $this->varname; +echo $this->_varName; +echo $this->varName2; +echo $object->varName; +echo $object->var_name; +echo $object->varName2; +echo $object_name->varname; +echo $object_name->_varName; +echo $object_name->varName2; + +echo $this->myFunction($one, $two); +echo $object->myFunction($one_two, $var2); + +$error = "format is \$GLOBALS['$varName']"; +$error = "format is \$GLOBALS['$varName2']"; + +echo $_SESSION['var_name']; +echo $_FILES['var_name']; +echo $_ENV['var_name']; +echo $_COOKIE['var_name']; +echo $_COOKIE['var_name2']; + +$XML = 'hello'; +$myXML = 'hello'; +$XMLParser = 'hello'; +$xmlParser = 'hello'; +$xmlParser2 = 'hello'; + +echo "{$_SERVER['HOSTNAME']} $var_name"; + +$someObject->{$name}; +$someObject->my_function($var_name); + +var_dump($http_response_header); +var_dump($HTTP_RAW_POST_DATA); +var_dump($php_errormsg); + +interface Base +{ + protected $anonymous; + + public function __construct(); +} + +$anonClass = new class() { + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +}; + +echo $obj?->varName; +echo $obj?->var_name; +echo $obj?->varName; + +enum SomeEnum +{ + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 000000000..e57c73564 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,96 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 11 => 1, + 13 => 1, + 17 => 1, + 19 => 1, + 23 => 1, + 25 => 1, + 29 => 1, + 31 => 1, + 36 => 1, + 38 => 1, + 42 => 1, + 44 => 1, + 48 => 1, + 50 => 1, + 61 => 1, + 67 => 1, + 72 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + 79 => 1, + 96 => 1, + 99 => 1, + 113 => 1, + 116 => 1, + 121 => 1, + 126 => 1, + 129 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 6 => 1, + 14 => 1, + 20 => 1, + 26 => 1, + 32 => 1, + 39 => 1, + 45 => 1, + 51 => 1, + 64 => 1, + 70 => 1, + 73 => 1, + 76 => 1, + 79 => 1, + 82 => 1, + 94 => 1, + 107 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml new file mode 100644 index 000000000..d10b10395 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml @@ -0,0 +1,32 @@ + + + A coding standard based on an early Zend Framework coding standard. Note that this standard is out of date. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/CSS.php b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/CSS.php new file mode 100644 index 000000000..b7c2018bc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/CSS.php @@ -0,0 +1,537 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +class CSS extends PHP +{ + + + /** + * Initialise the tokenizer. + * + * Pre-checks the content to see if it looks minified. + * + * @param string $content The content to tokenize, + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, Config $config, $eolChar='\n') + { + if ($this->isMinifiedContent($content, $eolChar) === true) { + throw new TokenizerException('File appears to be minified and cannot be processed'); + } + + parent::__construct($content, $config, $eolChar); + + }//end __construct() + + + /** + * Creates an array of tokens when given some CSS code. + * + * Uses the PHP tokenizer to do all the tricky work + * + * @param string $string The string to tokenize. + * + * @return array + */ + public function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START CSS TOKENIZING 1ST PASS ***".PHP_EOL; + } + + // If the content doesn't have an EOL char on the end, add one so + // the open and close tags we add are parsed correctly. + $eolAdded = false; + if (substr($string, (strlen($this->eolChar) * -1)) !== $this->eolChar) { + $string .= $this->eolChar; + $eolAdded = true; + } + + $string = str_replace('', '^PHPCS_CSS_T_CLOSE_TAG^', $string); + $tokens = parent::tokenize(''); + + $finalTokens = []; + $finalTokens[0] = [ + 'code' => T_OPEN_TAG, + 'type' => 'T_OPEN_TAG', + 'content' => '', + ]; + + $newStackPtr = 1; + $numTokens = count($tokens); + $multiLineComment = false; + for ($stackPtr = 1; $stackPtr < $numTokens; $stackPtr++) { + $token = $tokens[$stackPtr]; + + // CSS files don't have lists, breaks etc, so convert these to + // standard strings early so they can be converted into T_STYLE + // tokens and joined with other strings if needed. + if ($token['code'] === T_BREAK + || $token['code'] === T_LIST + || $token['code'] === T_DEFAULT + || $token['code'] === T_SWITCH + || $token['code'] === T_FOR + || $token['code'] === T_FOREACH + || $token['code'] === T_WHILE + || $token['code'] === T_DEC + || $token['code'] === T_NEW + ) { + $token['type'] = 'T_STRING'; + $token['code'] = T_STRING; + } + + $token['content'] = str_replace('^PHPCS_CSS_T_OPEN_TAG^', '', $token['content']); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + if ($token['code'] === T_BITWISE_XOR + && $tokens[($stackPtr + 1)]['content'] === 'PHPCS_CSS_T_OPEN_TAG' + ) { + $content = ''; + $stackPtr += 2; + break; + } else { + $content .= $tokens[$stackPtr]['content']; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> Found embedded PHP code: "; + $cleanContent = Util\Common::prepareForOutput($content); + echo $cleanContent.PHP_EOL; + } + + $finalTokens[$newStackPtr] = [ + 'type' => 'T_EMBEDDED_PHP', + 'code' => T_EMBEDDED_PHP, + 'content' => $content, + ]; + + $newStackPtr++; + continue; + }//end if + + if ($token['code'] === T_GOTO_LABEL) { + // Convert these back to T_STRING followed by T_COLON so we can + // more easily process style definitions. + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => substr($token['content'], 0, -1), + ]; + $newStackPtr++; + $finalTokens[$newStackPtr] = [ + 'type' => 'T_COLON', + 'code' => T_COLON, + 'content' => ':', + ]; + $newStackPtr++; + continue; + } + + if ($token['code'] === T_FUNCTION) { + // There are no functions in CSS, so convert this to a string. + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => $token['content'], + ]; + + $newStackPtr++; + continue; + } + + if ($token['code'] === T_COMMENT + && substr($token['content'], 0, 2) === '/*' + ) { + // Multi-line comment. Record it so we can ignore other + // comment tags until we get out of this one. + $multiLineComment = true; + } + + if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content'][0] === '#') + ) { + $content = ltrim($token['content'], '#/'); + + // Guard against PHP7+ syntax errors by stripping + // leading zeros so the content doesn't look like an invalid int. + $leadingZero = false; + if ($content[0] === '0') { + $content = '1'.$content; + $leadingZero = true; + } + + $commentTokens = parent::tokenize(''); + + // The first and last tokens are the open/close tags. + array_shift($commentTokens); + array_pop($commentTokens); + + if ($leadingZero === true) { + $commentTokens[0]['content'] = substr($commentTokens[0]['content'], 1); + $content = substr($content, 1); + } + + if ($token['content'][0] === '#') { + // The # character is not a comment in CSS files, so + // determine what it means in this context. + $firstContent = $commentTokens[0]['content']; + + // If the first content is just a number, it is probably a + // colour like 8FB7DB, which PHP splits into 8 and FB7DB. + if (($commentTokens[0]['code'] === T_LNUMBER + || $commentTokens[0]['code'] === T_DNUMBER) + && $commentTokens[1]['code'] === T_STRING + ) { + $firstContent .= $commentTokens[1]['content']; + array_shift($commentTokens); + } + + // If the first content looks like a colour and not a class + // definition, join the tokens together. + if (preg_match('/^[ABCDEF0-9]+$/i', $firstContent) === 1 + && $commentTokens[1]['content'] !== '-' + ) { + array_shift($commentTokens); + // Work out what we trimmed off above and remember to re-add it. + $trimmed = substr($token['content'], 0, (strlen($token['content']) - strlen($content))); + $finalTokens[$newStackPtr] = [ + 'type' => 'T_COLOUR', + 'code' => T_COLOUR, + 'content' => $trimmed.$firstContent, + ]; + } else { + $finalTokens[$newStackPtr] = [ + 'type' => 'T_HASH', + 'code' => T_HASH, + 'content' => '#', + ]; + } + } else { + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => '//', + ]; + }//end if + + $newStackPtr++; + + array_splice($tokens, $stackPtr, 1, $commentTokens); + $numTokens = count($tokens); + $stackPtr--; + continue; + }//end if + + if ($token['code'] === T_COMMENT + && substr($token['content'], -2) === '*/' + ) { + // Multi-line comment is done. + $multiLineComment = false; + } + + $finalTokens[$newStackPtr] = $token; + $newStackPtr++; + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END CSS TOKENIZING 1ST PASS ***".PHP_EOL; + echo "\t*** START CSS TOKENIZING 2ND PASS ***".PHP_EOL; + } + + // A flag to indicate if we are inside a style definition, + // which is defined using curly braces. + $inStyleDef = false; + + // A flag to indicate if an At-rule like "@media" is used, which will result + // in nested curly brackets. + $asperandStart = false; + + $numTokens = count($finalTokens); + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + $token = $finalTokens[$stackPtr]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + switch ($token['code']) { + case T_OPEN_CURLY_BRACKET: + // Opening curly brackets for an At-rule do not start a style + // definition. We also reset the asperand flag here because the next + // opening curly bracket could be indeed the start of a style + // definition. + if ($asperandStart === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inStyleDef === true) { + echo "\t\t* style definition closed *".PHP_EOL; + } + + if ($asperandStart === true) { + echo "\t\t* at-rule definition closed *".PHP_EOL; + } + } + + $inStyleDef = false; + $asperandStart = false; + } else { + $inStyleDef = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* style definition opened *".PHP_EOL; + } + } + break; + case T_CLOSE_CURLY_BRACKET: + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inStyleDef === true) { + echo "\t\t* style definition closed *".PHP_EOL; + } + + if ($asperandStart === true) { + echo "\t\t* at-rule definition closed *".PHP_EOL; + } + } + + $inStyleDef = false; + $asperandStart = false; + break; + case T_MINUS: + // Minus signs are often used instead of spaces inside + // class names, IDs and styles. + if ($finalTokens[($stackPtr + 1)]['code'] === T_STRING) { + if ($finalTokens[($stackPtr - 1)]['code'] === T_STRING) { + $newContent = $finalTokens[($stackPtr - 1)]['content'].'-'.$finalTokens[($stackPtr + 1)]['content']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL; + $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + $new = Util\Common::prepareForOutput($newContent); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + unset($finalTokens[($stackPtr - 1)]); + } else { + $newContent = '-'.$finalTokens[($stackPtr + 1)]['content']; + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + } + } else if ($finalTokens[($stackPtr + 1)]['code'] === T_LNUMBER) { + // They can also be used to provide negative numbers. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is part of a negative number; adding content to next token and ignoring *".PHP_EOL; + $content = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$content\" to \"-$content\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = '-'.$finalTokens[($stackPtr + 1)]['content']; + unset($finalTokens[$stackPtr]); + }//end if + break; + case T_COLON: + // Only interested in colons that are defining styles. + if ($inStyleDef === false) { + break; + } + + for ($x = ($stackPtr - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) { + break; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $finalTokens[$x]['type']; + echo "\t\t=> token $x changed from $type to T_STYLE".PHP_EOL; + } + + $finalTokens[$x]['type'] = 'T_STYLE'; + $finalTokens[$x]['code'] = T_STYLE; + break; + case T_STRING: + if (strtolower($token['content']) === 'url') { + // Find the next content. + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) { + break; + } + } + + // Needs to be in the format "url(" for it to be a URL. + if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) { + continue 2; + } + + // Make sure the content isn't empty. + for ($y = ($x + 1); $y < $numTokens; $y++) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$y]['code']]) === false) { + break; + } + } + + if ($finalTokens[$y]['code'] === T_CLOSE_PARENTHESIS) { + continue 2; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= $y; $i++) { + $type = $finalTokens[$i]['type']; + $content = Util\Common::prepareForOutput($finalTokens[$i]['content']); + echo "\tProcess token $i: $type => $content".PHP_EOL; + } + + echo "\t\t* token starts a URL *".PHP_EOL; + } + + // Join all the content together inside the url() statement. + $newContent = ''; + for ($i = ($x + 2); $i < $numTokens; $i++) { + if ($finalTokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + + $newContent .= $finalTokens[$i]['content']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($finalTokens[$i]['content']); + echo "\t\t=> token $i added to URL string and ignored: $content".PHP_EOL; + } + + unset($finalTokens[$i]); + } + + $stackPtr = $i; + + // If the content inside the "url()" is in double quotes + // there will only be one token and so we don't have to do + // anything except change its type. If it is not empty, + // we need to do some token merging. + $finalTokens[($x + 1)]['type'] = 'T_URL'; + $finalTokens[($x + 1)]['code'] = T_URL; + + if ($newContent !== '') { + $finalTokens[($x + 1)]['content'] .= $newContent; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($finalTokens[($x + 1)]['content']); + echo "\t\t=> token content changed to: $content".PHP_EOL; + } + } + } else if ($finalTokens[$stackPtr]['content'][0] === '-' + && $finalTokens[($stackPtr + 1)]['code'] === T_STRING + ) { + if (isset($finalTokens[($stackPtr - 1)]) === true + && $finalTokens[($stackPtr - 1)]['code'] === T_STRING + ) { + $newContent = $finalTokens[($stackPtr - 1)]['content'].$finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL; + $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + $new = Util\Common::prepareForOutput($newContent); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + unset($finalTokens[($stackPtr - 1)]); + } else { + $newContent = $finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content']; + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + } + }//end if + break; + case T_ASPERAND: + $asperandStart = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* at-rule definition opened *".PHP_EOL; + } + break; + default: + // Nothing special to be done with this token. + break; + }//end switch + }//end for + + // Reset the array keys to avoid gaps. + $finalTokens = array_values($finalTokens); + $numTokens = count($finalTokens); + + // Blank out the content of the end tag. + $finalTokens[($numTokens - 1)]['content'] = ''; + + if ($eolAdded === true) { + // Strip off the extra EOL char we added for tokenizing. + $finalTokens[($numTokens - 2)]['content'] = substr( + $finalTokens[($numTokens - 2)]['content'], + 0, + (strlen($this->eolChar) * -1) + ); + + if ($finalTokens[($numTokens - 2)]['content'] === '') { + unset($finalTokens[($numTokens - 2)]); + $finalTokens = array_values($finalTokens); + $numTokens = count($finalTokens); + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END CSS TOKENIZING 2ND PASS ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Performs additional processing after main tokenizing. + * + * @return void + */ + public function processAdditional() + { + /* + We override this method because we don't want the PHP version to + run during CSS processing because it is wasted processing time. + */ + + }//end processAdditional() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Comment.php b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Comment.php new file mode 100644 index 000000000..beba53c2b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Comment.php @@ -0,0 +1,277 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Util; + +class Comment +{ + + + /** + * Creates an array of tokens when given some PHP code. + * + * Starts by using token_get_all() but does a lot of extra processing + * to insert information about the context of the token. + * + * @param string $string The string to tokenize. + * @param string $eolChar The EOL character to use for splitting strings. + * @param int $stackPtr The position of the first token in the file. + * + * @return array + */ + public function tokenizeString($string, $eolChar, $stackPtr) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL; + } + + $tokens = []; + $numChars = strlen($string); + + /* + Doc block comments start with /*, but typically contain an + extra star when they are used for function and class comments. + */ + + $char = ($numChars - strlen(ltrim($string, '/*'))); + $openTag = substr($string, 0, $char); + $string = ltrim($string, '/*'); + + $tokens[$stackPtr] = [ + 'content' => $openTag, + 'code' => T_DOC_COMMENT_OPEN_TAG, + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'comment_tags' => [], + ]; + + $openPtr = $stackPtr; + $stackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($openTag); + echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL; + } + + /* + Strip off the close tag so it doesn't interfere with any + of our comment line processing. The token will be added to the + stack just before we return it. + */ + + $closeTag = [ + 'content' => substr($string, strlen(rtrim($string, '/*'))), + 'code' => T_DOC_COMMENT_CLOSE_TAG, + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'comment_opener' => $openPtr, + ]; + + if ($closeTag['content'] === false) { + $closeTag['content'] = ''; + } + + $string = rtrim($string, '/*'); + + /* + Process each line of the comment. + */ + + $lines = explode($eolChar, $string); + $numLines = count($lines); + foreach ($lines as $lineNum => $string) { + if ($lineNum !== ($numLines - 1)) { + $string .= $eolChar; + } + + $char = 0; + $numChars = strlen($string); + + // We've started a new line, so process the indent. + $space = $this->collectWhitespace($string, $char, $numChars); + if ($space !== null) { + $tokens[$stackPtr] = $space; + $stackPtr++; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($space['content']); + echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL; + } + + $char += strlen($space['content']); + if ($char === $numChars) { + break; + } + } + + if ($string === '') { + continue; + } + + if ($lineNum > 0 && $string[$char] === '*') { + // This is a function or class doc block line. + $char++; + $tokens[$stackPtr] = [ + 'content' => '*', + 'code' => T_DOC_COMMENT_STAR, + 'type' => 'T_DOC_COMMENT_STAR', + ]; + + $stackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL; + } + } + + // Now we are ready to process the actual content of the line. + $lineTokens = $this->processLine($string, $eolChar, $char, $numChars); + foreach ($lineTokens as $lineToken) { + $tokens[$stackPtr] = $lineToken; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($lineToken['content']); + $type = $lineToken['type']; + echo "\t\tCreate comment token: $type => $content".PHP_EOL; + } + + if ($lineToken['code'] === T_DOC_COMMENT_TAG) { + $tokens[$openPtr]['comment_tags'][] = $stackPtr; + } + + $stackPtr++; + } + }//end foreach + + $tokens[$stackPtr] = $closeTag; + $tokens[$openPtr]['comment_closer'] = $stackPtr; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($closeTag['content']); + echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL; + } + + return $tokens; + + }//end tokenizeString() + + + /** + * Process a single line of a comment. + * + * @param string $string The comment string being tokenized. + * @param string $eolChar The EOL character to use for splitting strings. + * @param int $start The position in the string to start processing. + * @param int $end The position in the string to end processing. + * + * @return array + */ + private function processLine($string, $eolChar, $start, $end) + { + $tokens = []; + + // Collect content padding. + $space = $this->collectWhitespace($string, $start, $end); + if ($space !== null) { + $tokens[] = $space; + $start += strlen($space['content']); + } + + if (isset($string[$start]) === false) { + return $tokens; + } + + if ($string[$start] === '@') { + // The content up until the first whitespace is the tag name. + $matches = []; + preg_match('/@[^\s]+/', $string, $matches, 0, $start); + if (isset($matches[0]) === true + && substr(strtolower($matches[0]), 0, 7) !== '@phpcs:' + ) { + $tagName = $matches[0]; + $start += strlen($tagName); + $tokens[] = [ + 'content' => $tagName, + 'code' => T_DOC_COMMENT_TAG, + 'type' => 'T_DOC_COMMENT_TAG', + ]; + + // Then there will be some whitespace. + $space = $this->collectWhitespace($string, $start, $end); + if ($space !== null) { + $tokens[] = $space; + $start += strlen($space['content']); + } + } + }//end if + + // Process the rest of the line. + $eol = strpos($string, $eolChar, $start); + if ($eol === false) { + $eol = $end; + } + + if ($eol > $start) { + $tokens[] = [ + 'content' => substr($string, $start, ($eol - $start)), + 'code' => T_DOC_COMMENT_STRING, + 'type' => 'T_DOC_COMMENT_STRING', + ]; + } + + if ($eol !== $end) { + $tokens[] = [ + 'content' => substr($string, $eol, strlen($eolChar)), + 'code' => T_DOC_COMMENT_WHITESPACE, + 'type' => 'T_DOC_COMMENT_WHITESPACE', + ]; + } + + return $tokens; + + }//end processLine() + + + /** + * Collect consecutive whitespace into a single token. + * + * @param string $string The comment string being tokenized. + * @param int $start The position in the string to start processing. + * @param int $end The position in the string to end processing. + * + * @return array|null + */ + private function collectWhitespace($string, $start, $end) + { + $space = ''; + for ($start; $start < $end; $start++) { + if ($string[$start] !== ' ' && $string[$start] !== "\t") { + break; + } + + $space .= $string[$start]; + } + + if ($space === '') { + return null; + } + + $token = [ + 'content' => $space, + 'code' => T_DOC_COMMENT_WHITESPACE, + 'type' => 'T_DOC_COMMENT_WHITESPACE', + ]; + + return $token; + + }//end collectWhitespace() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/JS.php b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/JS.php new file mode 100644 index 000000000..ee2f84294 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/JS.php @@ -0,0 +1,1256 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +class JS extends Tokenizer +{ + + /** + * A list of tokens that are allowed to open a scope. + * + * This array also contains information about what kind of token the scope + * opener uses to open and close the scope, if the token strictly requires + * an opener, if the token can share a scope closer, and who it can be shared + * with. An example of a token that shares a scope closer is a CASE scope. + * + * @var array + */ + public $scopeOpeners = [ + T_IF => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_TRY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ELSE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_FOR => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_CLASS => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FUNCTION => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_WHILE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DO => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_SWITCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CASE => [ + 'start' => [T_COLON => T_COLON], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_DEFAULT => T_DEFAULT, + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_DEFAULT => [ + 'start' => [T_COLON => T_COLON], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + ]; + + /** + * A list of tokens that end the scope. + * + * This array is just a unique collection of the end tokens + * from the _scopeOpeners array. The data is duplicated here to + * save time during parsing of the file. + * + * @var array + */ + public $endScopeTokens = [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_BREAK => T_BREAK, + ]; + + /** + * A list of special JS tokens and their types. + * + * @var array + */ + protected $tokenValues = [ + 'class' => 'T_CLASS', + 'function' => 'T_FUNCTION', + 'prototype' => 'T_PROTOTYPE', + 'try' => 'T_TRY', + 'catch' => 'T_CATCH', + 'return' => 'T_RETURN', + 'throw' => 'T_THROW', + 'break' => 'T_BREAK', + 'switch' => 'T_SWITCH', + 'continue' => 'T_CONTINUE', + 'if' => 'T_IF', + 'else' => 'T_ELSE', + 'do' => 'T_DO', + 'while' => 'T_WHILE', + 'for' => 'T_FOR', + 'var' => 'T_VAR', + 'case' => 'T_CASE', + 'default' => 'T_DEFAULT', + 'true' => 'T_TRUE', + 'false' => 'T_FALSE', + 'null' => 'T_NULL', + 'this' => 'T_THIS', + 'typeof' => 'T_TYPEOF', + '(' => 'T_OPEN_PARENTHESIS', + ')' => 'T_CLOSE_PARENTHESIS', + '{' => 'T_OPEN_CURLY_BRACKET', + '}' => 'T_CLOSE_CURLY_BRACKET', + '[' => 'T_OPEN_SQUARE_BRACKET', + ']' => 'T_CLOSE_SQUARE_BRACKET', + '?' => 'T_INLINE_THEN', + '.' => 'T_OBJECT_OPERATOR', + '+' => 'T_PLUS', + '-' => 'T_MINUS', + '*' => 'T_MULTIPLY', + '%' => 'T_MODULUS', + '/' => 'T_DIVIDE', + '^' => 'T_LOGICAL_XOR', + ',' => 'T_COMMA', + ';' => 'T_SEMICOLON', + ':' => 'T_COLON', + '<' => 'T_LESS_THAN', + '>' => 'T_GREATER_THAN', + '<<' => 'T_SL', + '>>' => 'T_SR', + '>>>' => 'T_ZSR', + '<<=' => 'T_SL_EQUAL', + '>>=' => 'T_SR_EQUAL', + '>>>=' => 'T_ZSR_EQUAL', + '<=' => 'T_IS_SMALLER_OR_EQUAL', + '>=' => 'T_IS_GREATER_OR_EQUAL', + '=>' => 'T_DOUBLE_ARROW', + '!' => 'T_BOOLEAN_NOT', + '||' => 'T_BOOLEAN_OR', + '&&' => 'T_BOOLEAN_AND', + '|' => 'T_BITWISE_OR', + '&' => 'T_BITWISE_AND', + '!=' => 'T_IS_NOT_EQUAL', + '!==' => 'T_IS_NOT_IDENTICAL', + '=' => 'T_EQUAL', + '==' => 'T_IS_EQUAL', + '===' => 'T_IS_IDENTICAL', + '-=' => 'T_MINUS_EQUAL', + '+=' => 'T_PLUS_EQUAL', + '*=' => 'T_MUL_EQUAL', + '/=' => 'T_DIV_EQUAL', + '%=' => 'T_MOD_EQUAL', + '++' => 'T_INC', + '--' => 'T_DEC', + '//' => 'T_COMMENT', + '/*' => 'T_COMMENT', + '/**' => 'T_DOC_COMMENT', + '*/' => 'T_COMMENT', + ]; + + /** + * A list string delimiters. + * + * @var array + */ + protected $stringTokens = [ + '\'' => '\'', + '"' => '"', + ]; + + /** + * A list tokens that start and end comments. + * + * @var array + */ + protected $commentTokens = [ + '//' => null, + '/*' => '*/', + '/**' => '*/', + ]; + + + /** + * Initialise the tokenizer. + * + * Pre-checks the content to see if it looks minified. + * + * @param string $content The content to tokenize, + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, Config $config, $eolChar='\n') + { + if ($this->isMinifiedContent($content, $eolChar) === true) { + throw new TokenizerException('File appears to be minified and cannot be processed'); + } + + parent::__construct($content, $config, $eolChar); + + }//end __construct() + + + /** + * Creates an array of tokens when given some JS code. + * + * @param string $string The string to tokenize. + * + * @return array + */ + public function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START JS TOKENIZING ***".PHP_EOL; + } + + $maxTokenLength = 0; + foreach ($this->tokenValues as $token => $values) { + if (strlen($token) > $maxTokenLength) { + $maxTokenLength = strlen($token); + } + } + + $tokens = []; + $inString = ''; + $stringChar = null; + $inComment = ''; + $buffer = ''; + $preStringBuffer = ''; + $cleanBuffer = false; + + $commentTokenizer = new Comment(); + + $tokens[] = [ + 'code' => T_OPEN_TAG, + 'type' => 'T_OPEN_TAG', + 'content' => '', + ]; + + // Convert newlines to single characters for ease of + // processing. We will change them back later. + $string = str_replace($this->eolChar, "\n", $string); + + $chars = str_split($string); + $numChars = count($chars); + for ($i = 0; $i < $numChars; $i++) { + $char = $chars[$i]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($char); + $bufferContent = Util\Common::prepareForOutput($buffer); + + if ($inString !== '') { + echo "\t"; + } + + if ($inComment !== '') { + echo "\t"; + } + + echo "\tProcess char $i => $content (buffer: $bufferContent)".PHP_EOL; + }//end if + + if ($inString === '' && $inComment === '' && $buffer !== '') { + // If the buffer only has whitespace and we are about to + // add a character, store the whitespace first. + if (trim($char) !== '' && trim($buffer) === '') { + $tokens[] = [ + 'code' => T_WHITESPACE, + 'type' => 'T_WHITESPACE', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL; + } + + $buffer = ''; + } + + // If the buffer is not whitespace and we are about to + // add a whitespace character, store the content first. + if ($inString === '' + && $inComment === '' + && trim($char) === '' + && trim($buffer) !== '' + ) { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + } + }//end if + + // Process strings. + if ($inComment === '' && isset($this->stringTokens[$char]) === true) { + if ($inString === $char) { + // This could be the end of the string, but make sure it + // is not escaped first. + $escapes = 0; + for ($x = ($i - 1); $x >= 0; $x--) { + if ($chars[$x] !== '\\') { + break; + } + + $escapes++; + } + + if ($escapes === 0 || ($escapes % 2) === 0) { + // There is an even number escape chars, + // so this is not escaped, it is the end of the string. + $tokens[] = [ + 'code' => T_CONSTANT_ENCAPSED_STRING, + 'type' => 'T_CONSTANT_ENCAPSED_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer).$char, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* found end of string *".PHP_EOL; + $content = Util\Common::prepareForOutput($buffer.$char); + echo "\t=> Added token T_CONSTANT_ENCAPSED_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + $preStringBuffer = ''; + $inString = ''; + $stringChar = null; + continue; + }//end if + } else if ($inString === '') { + $inString = $char; + $stringChar = $i; + $preStringBuffer = $buffer; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* looking for string closer *".PHP_EOL; + } + }//end if + }//end if + + if ($inString !== '' && $char === "\n") { + // Unless this newline character is escaped, the string did not + // end before the end of the line, which means it probably + // wasn't a string at all (maybe a regex). + if ($chars[($i - 1)] !== '\\') { + $i = $stringChar; + $buffer = $preStringBuffer; + $preStringBuffer = ''; + $inString = ''; + $stringChar = null; + $char = $chars[$i]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* found newline before end of string, bailing *".PHP_EOL; + } + } + } + + $buffer .= $char; + + // We don't look for special tokens inside strings, + // so if we are in a string, we can continue here now + // that the current char is in the buffer. + if ($inString !== '') { + continue; + } + + // Special case for T_DIVIDE which can actually be + // the start of a regular expression. + if ($buffer === $char && $char === '/' && $chars[($i + 1)] !== '*') { + $regex = $this->getRegexToken($i, $string, $chars, $tokens); + if ($regex !== null) { + $tokens[] = [ + 'code' => T_REGULAR_EXPRESSION, + 'type' => 'T_REGULAR_EXPRESSION', + 'content' => $regex['content'], + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($regex['content']); + echo "\t=> Added token T_REGULAR_EXPRESSION ($content)".PHP_EOL; + } + + $i = $regex['end']; + $buffer = ''; + $cleanBuffer = false; + continue; + }//end if + }//end if + + // Check for known tokens, but ignore tokens found that are not at + // the end of a string, like FOR and this.FORmat. + if (isset($this->tokenValues[strtolower($buffer)]) === true + && (preg_match('|[a-zA-z0-9_]|', $char) === 0 + || isset($chars[($i + 1)]) === false + || preg_match('|[a-zA-z0-9_]|', $chars[($i + 1)]) === 0) + ) { + $matchedToken = false; + $lookAheadLength = ($maxTokenLength - strlen($buffer)); + + if ($lookAheadLength > 0) { + // The buffer contains a token type, but we need + // to look ahead at the next chars to see if this is + // actually part of a larger token. For example, + // FOR and FOREACH. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* buffer possibly contains token, looking ahead $lookAheadLength chars *".PHP_EOL; + } + + $charBuffer = $buffer; + for ($x = 1; $x <= $lookAheadLength; $x++) { + if (isset($chars[($i + $x)]) === false) { + break; + } + + $charBuffer .= $chars[($i + $x)]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($charBuffer); + echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL; + } + + if (isset($this->tokenValues[strtolower($charBuffer)]) === true) { + // We've found something larger that matches + // so we can ignore this char. Except for 1 very specific + // case where a comment like /**/ needs to tokenize as + // T_COMMENT and not T_DOC_COMMENT. + $oldType = $this->tokenValues[strtolower($buffer)]; + $newType = $this->tokenValues[strtolower($charBuffer)]; + if ($oldType === 'T_COMMENT' + && $newType === 'T_DOC_COMMENT' + && $chars[($i + $x + 1)] === '/' + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead ignored T_DOC_COMMENT, continuing *".PHP_EOL; + } + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead found more specific token ($newType), ignoring $i *".PHP_EOL; + } + + $matchedToken = true; + break; + } + }//end if + }//end for + }//end if + + if ($matchedToken === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1 && $lookAheadLength > 0) { + echo "\t\t* look ahead found nothing *".PHP_EOL; + } + + $value = $this->tokenValues[strtolower($buffer)]; + + if ($value === 'T_FUNCTION' && $buffer !== 'function') { + // The function keyword needs to be all lowercase or else + // it is just a function called "Function". + $value = 'T_STRING'; + } + + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $buffer, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + + $cleanBuffer = true; + }//end if + } else if (isset($this->tokenValues[strtolower($char)]) === true) { + // No matter what token we end up using, we don't + // need the content in the buffer any more because we have + // found a valid token. + $newContent = substr(str_replace("\n", $this->eolChar, $buffer), 0, -1); + if ($newContent !== '') { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $newContent, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput(substr($buffer, 0, -1)); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* char is token, looking ahead ".($maxTokenLength - 1).' chars *'.PHP_EOL; + } + + // The char is a token type, but we need to look ahead at the + // next chars to see if this is actually part of a larger token. + // For example, = and ===. + $charBuffer = $char; + $matchedToken = false; + for ($x = 1; $x <= $maxTokenLength; $x++) { + if (isset($chars[($i + $x)]) === false) { + break; + } + + $charBuffer .= $chars[($i + $x)]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($charBuffer); + echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL; + } + + if (isset($this->tokenValues[strtolower($charBuffer)]) === true) { + // We've found something larger that matches + // so we can ignore this char. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokenValues[strtolower($charBuffer)]; + echo "\t\t* look ahead found more specific token ($type), ignoring $i *".PHP_EOL; + } + + $matchedToken = true; + break; + } + }//end for + + if ($matchedToken === false) { + $value = $this->tokenValues[strtolower($char)]; + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $char, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead found nothing *".PHP_EOL; + $content = Util\Common::prepareForOutput($char); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + + $cleanBuffer = true; + } else { + $buffer = $char; + }//end if + }//end if + + // Keep track of content inside comments. + if ($inComment === '' + && array_key_exists($buffer, $this->commentTokens) === true + ) { + // This is not really a comment if the content + // looks like \// (i.e., it is escaped). + if (isset($chars[($i - 2)]) === true && $chars[($i - 2)] === '\\') { + $lastToken = array_pop($tokens); + $lastContent = $lastToken['content']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $value = $this->tokenValues[strtolower($lastContent)]; + $content = Util\Common::prepareForOutput($lastContent); + echo "\t=> Removed token $value ($content)".PHP_EOL; + } + + $lastChars = str_split($lastContent); + $lastNumChars = count($lastChars); + for ($x = 0; $x < $lastNumChars; $x++) { + $lastChar = $lastChars[$x]; + $value = $this->tokenValues[strtolower($lastChar)]; + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $lastChar, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($lastChar); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + } + } else { + // We have started a comment. + $inComment = $buffer; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* looking for end of comment *".PHP_EOL; + } + }//end if + } else if ($inComment !== '') { + if ($this->commentTokens[$inComment] === null) { + // Comment ends at the next newline. + if (strpos($buffer, "\n") !== false) { + $inComment = ''; + } + } else { + if ($this->commentTokens[$inComment] === $buffer) { + $inComment = ''; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inComment === '') { + echo "\t\t* found end of comment *".PHP_EOL; + } + } + + if ($inComment === '' && $cleanBuffer === false) { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + } + }//end if + + if ($cleanBuffer === true) { + $buffer = ''; + $cleanBuffer = false; + } + }//end for + + if (empty($buffer) === false) { + if ($inString !== '') { + // The string did not end before the end of the file, + // which means there was probably a syntax error somewhere. + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + } else { + // Buffer contains whitespace from the end of the file. + $tokens[] = [ + 'code' => T_WHITESPACE, + 'type' => 'T_WHITESPACE', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL; + } + }//end if + }//end if + + $tokens[] = [ + 'code' => T_CLOSE_TAG, + 'type' => 'T_CLOSE_TAG', + 'content' => '', + ]; + + /* + Now that we have done some basic tokenizing, we need to + modify the tokens to join some together and split some apart + so they match what the PHP tokenizer does. + */ + + $finalTokens = []; + $newStackPtr = 0; + $numTokens = count($tokens); + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + $token = $tokens[$stackPtr]; + + /* + Look for comments and join the tokens together. + */ + + if ($token['code'] === T_COMMENT || $token['code'] === T_DOC_COMMENT) { + $newContent = ''; + $tokenContent = $token['content']; + + $endContent = null; + if (isset($this->commentTokens[$tokenContent]) === true) { + $endContent = $this->commentTokens[$tokenContent]; + } + + while ($tokenContent !== $endContent) { + if ($endContent === null + && strpos($tokenContent, $this->eolChar) !== false + ) { + // A null end token means the comment ends at the end of + // the line so we look for newlines and split the token. + $tokens[$stackPtr]['content'] = substr( + $tokenContent, + (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar)) + ); + + $tokenContent = substr( + $tokenContent, + 0, + (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar)) + ); + + // If the substr failed, skip the token as the content + // will now be blank. + if ($tokens[$stackPtr]['content'] !== false + && $tokens[$stackPtr]['content'] !== '' + ) { + $stackPtr--; + } + + break; + }//end if + + $stackPtr++; + $newContent .= $tokenContent; + if (isset($tokens[$stackPtr]) === false) { + break; + } + + $tokenContent = $tokens[$stackPtr]['content']; + }//end while + + if ($token['code'] === T_DOC_COMMENT) { + $commentTokens = $commentTokenizer->tokenizeString($newContent.$tokenContent, $this->eolChar, $newStackPtr); + foreach ($commentTokens as $commentToken) { + $finalTokens[$newStackPtr] = $commentToken; + $newStackPtr++; + } + + continue; + } else { + // Save the new content in the current token so + // the code below can chop it up on newlines. + $token['content'] = $newContent.$tokenContent; + } + }//end if + + /* + If this token has newlines in its content, split each line up + and create a new token for each line. We do this so it's easier + to ascertain where errors occur on a line. + Note that $token[1] is the token's content. + */ + + if (strpos($token['content'], $this->eolChar) !== false) { + $tokenLines = explode($this->eolChar, $token['content']); + $numLines = count($tokenLines); + + for ($i = 0; $i < $numLines; $i++) { + $newToken = ['content' => $tokenLines[$i]]; + if ($i === ($numLines - 1)) { + if ($tokenLines[$i] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $newToken['type'] = $token['type']; + $newToken['code'] = $token['code']; + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + } else { + $finalTokens[$newStackPtr] = $token; + $newStackPtr++; + }//end if + + // Convert numbers, including decimals. + if ($token['code'] === T_STRING + || $token['code'] === T_OBJECT_OPERATOR + ) { + $newContent = ''; + $oldStackPtr = $stackPtr; + while (preg_match('|^[0-9\.]+$|', $tokens[$stackPtr]['content']) !== 0) { + $newContent .= $tokens[$stackPtr]['content']; + $stackPtr++; + } + + if ($newContent !== '' && $newContent !== '.') { + $finalTokens[($newStackPtr - 1)]['content'] = $newContent; + if (ctype_digit($newContent) === true) { + $finalTokens[($newStackPtr - 1)]['code'] = constant('T_LNUMBER'); + $finalTokens[($newStackPtr - 1)]['type'] = 'T_LNUMBER'; + } else { + $finalTokens[($newStackPtr - 1)]['code'] = constant('T_DNUMBER'); + $finalTokens[($newStackPtr - 1)]['type'] = 'T_DNUMBER'; + } + + $stackPtr--; + continue; + } else { + $stackPtr = $oldStackPtr; + } + }//end if + + // Convert the token after an object operator into a string, in most cases. + if ($token['code'] === T_OBJECT_OPERATOR) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (isset(Util\Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if ($tokens[$i]['code'] !== T_PROTOTYPE + && $tokens[$i]['code'] !== T_LNUMBER + && $tokens[$i]['code'] !== T_DNUMBER + ) { + $tokens[$i]['code'] = T_STRING; + $tokens[$i]['type'] = 'T_STRING'; + } + + break; + } + } + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END TOKENIZING ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Tokenizes a regular expression if one is found. + * + * If a regular expression is not found, NULL is returned. + * + * @param string $char The index of the possible regex start character. + * @param string $string The complete content of the string being tokenized. + * @param string $chars An array of characters being tokenized. + * @param string $tokens The current array of tokens found in the string. + * + * @return array|null + */ + public function getRegexToken($char, $string, $chars, $tokens) + { + $beforeTokens = [ + T_EQUAL => true, + T_IS_NOT_EQUAL => true, + T_IS_IDENTICAL => true, + T_IS_NOT_IDENTICAL => true, + T_OPEN_PARENTHESIS => true, + T_OPEN_SQUARE_BRACKET => true, + T_RETURN => true, + T_BOOLEAN_OR => true, + T_BOOLEAN_AND => true, + T_BOOLEAN_NOT => true, + T_BITWISE_OR => true, + T_BITWISE_AND => true, + T_COMMA => true, + T_COLON => true, + T_TYPEOF => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + $afterTokens = [ + ',' => true, + ')' => true, + ']' => true, + ';' => true, + ' ' => true, + '.' => true, + ':' => true, + $this->eolChar => true, + ]; + + // Find the last non-whitespace token that was added + // to the tokens array. + $numTokens = count($tokens); + for ($prev = ($numTokens - 1); $prev >= 0; $prev--) { + if (isset(Util\Tokens::$emptyTokens[$tokens[$prev]['code']]) === false) { + break; + } + } + + if (isset($beforeTokens[$tokens[$prev]['code']]) === false) { + return null; + } + + // This is probably a regular expression, so look for the end of it. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* token possibly starts a regular expression *".PHP_EOL; + } + + $numChars = count($chars); + for ($next = ($char + 1); $next < $numChars; $next++) { + if ($chars[$next] === '/') { + // Just make sure this is not escaped first. + if ($chars[($next - 1)] !== '\\') { + // In the simple form: /.../ so we found the end. + break; + } else if ($chars[($next - 2)] === '\\') { + // In the form: /...\\/ so we found the end. + break; + } + } else { + $possibleEolChar = substr($string, $next, strlen($this->eolChar)); + if ($possibleEolChar === $this->eolChar) { + // This is the last token on the line and regular + // expressions need to be defined on a single line, + // so this is not a regular expression. + break; + } + } + } + + if ($chars[$next] !== '/') { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* could not find end of regular expression *".PHP_EOL; + } + + return null; + } + + while (preg_match('|[a-zA-Z]|', $chars[($next + 1)]) !== 0) { + // The token directly after the end of the regex can + // be modifiers like global and case insensitive + // (.e.g, /pattern/gi). + $next++; + } + + $regexEnd = $next; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* found end of regular expression at token $regexEnd *".PHP_EOL; + } + + for ($next += 1; $next < $numChars; $next++) { + if ($chars[$next] !== ' ') { + break; + } else { + $possibleEolChar = substr($string, $next, strlen($this->eolChar)); + if ($possibleEolChar === $this->eolChar) { + // This is the last token on the line. + break; + } + } + } + + if (isset($afterTokens[$chars[$next]]) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* tokens after regular expression do not look correct *".PHP_EOL; + } + + return null; + } + + // This is a regular expression, so join all the tokens together. + $content = ''; + for ($x = $char; $x <= $regexEnd; $x++) { + $content .= $chars[$x]; + } + + $token = [ + 'start' => $char, + 'end' => $regexEnd, + 'content' => $content, + ]; + + return $token; + + }//end getRegexToken() + + + /** + * Performs additional processing after main tokenizing. + * + * This additional processing looks for properties, closures, labels and objects. + * + * @return void + */ + public function processAdditional() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START ADDITIONAL JS PROCESSING ***".PHP_EOL; + } + + $numTokens = count($this->tokens); + $classStack = []; + + for ($i = 0; $i < $numTokens; $i++) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", count($classStack)); + echo "\tProcess token $i: $type => $content".PHP_EOL; + } + + // Looking for functions that are actually closures. + if ($this->tokens[$i]['code'] === T_FUNCTION && isset($this->tokens[$i]['scope_opener']) === true) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$i]['code'] = T_CLOSURE; + $this->tokens[$i]['type'] = 'T_CLOSURE'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo str_repeat("\t", count($classStack)); + echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE *".PHP_EOL; + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_CLOSURE; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + && isset($this->tokens[$i]['scope_condition']) === false + && isset($this->tokens[$i]['bracket_closer']) === true + ) { + $condition = $this->tokens[$i]['conditions']; + $condition = end($condition); + if ($condition === T_CLASS) { + // Possibly an ES6 method. To be classified as one, the previous + // non-empty tokens need to be a set of parenthesis, and then a string + // (the method name). + for ($parenCloser = ($i - 1); $parenCloser > 0; $parenCloser--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$parenCloser]['code']]) === false) { + break; + } + } + + if ($this->tokens[$parenCloser]['code'] === T_CLOSE_PARENTHESIS) { + $parenOpener = $this->tokens[$parenCloser]['parenthesis_opener']; + for ($name = ($parenOpener - 1); $name > 0; $name--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$name]['code']]) === false) { + break; + } + } + + if ($this->tokens[$name]['code'] === T_STRING) { + // We found a method name. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$name]['line']; + echo str_repeat("\t", count($classStack)); + echo "\t* token $name on line $line changed from T_STRING to T_FUNCTION *".PHP_EOL; + } + + $closer = $this->tokens[$i]['bracket_closer']; + + $this->tokens[$name]['code'] = T_FUNCTION; + $this->tokens[$name]['type'] = 'T_FUNCTION'; + + foreach ([$name, $i, $closer] as $token) { + $this->tokens[$token]['scope_condition'] = $name; + $this->tokens[$token]['scope_opener'] = $i; + $this->tokens[$token]['scope_closer'] = $closer; + $this->tokens[$token]['parenthesis_opener'] = $parenOpener; + $this->tokens[$token]['parenthesis_closer'] = $parenCloser; + $this->tokens[$token]['parenthesis_owner'] = $name; + } + + $this->tokens[$parenOpener]['parenthesis_owner'] = $name; + $this->tokens[$parenCloser]['parenthesis_owner'] = $name; + + for ($x = ($i + 1); $x < $closer; $x++) { + $this->tokens[$x]['conditions'][$name] = T_FUNCTION; + ksort($this->tokens[$x]['conditions'], SORT_NUMERIC); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* added T_FUNCTION condition to $x ($type) *".PHP_EOL; + } + } + + continue; + }//end if + }//end if + }//end if + + $classStack[] = $i; + + $closer = $this->tokens[$i]['bracket_closer']; + $this->tokens[$i]['code'] = T_OBJECT; + $this->tokens[$i]['type'] = 'T_OBJECT'; + $this->tokens[$closer]['code'] = T_CLOSE_OBJECT; + $this->tokens[$closer]['type'] = 'T_CLOSE_OBJECT'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $i converted from T_OPEN_CURLY_BRACKET to T_OBJECT *".PHP_EOL; + echo str_repeat("\t", count($classStack)); + echo "\t* token $closer converted from T_CLOSE_CURLY_BRACKET to T_CLOSE_OBJECT *".PHP_EOL; + } + + for ($x = ($i + 1); $x < $closer; $x++) { + $this->tokens[$x]['conditions'][$i] = T_OBJECT; + ksort($this->tokens[$x]['conditions'], SORT_NUMERIC); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* added T_OBJECT condition to $x ($type) *".PHP_EOL; + } + } + } else if ($this->tokens[$i]['code'] === T_CLOSE_OBJECT) { + $opener = array_pop($classStack); + } else if ($this->tokens[$i]['code'] === T_COLON) { + // If it is a scope opener, it belongs to a + // DEFAULT or CASE statement. + if (isset($this->tokens[$i]['scope_condition']) === true) { + continue; + } + + // Make sure this is not part of an inline IF statement. + for ($x = ($i - 1); $x >= 0; $x--) { + if ($this->tokens[$x]['code'] === T_INLINE_THEN) { + $this->tokens[$i]['code'] = T_INLINE_ELSE; + $this->tokens[$i]['type'] = 'T_INLINE_ELSE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $i converted from T_COLON to T_INLINE_THEN *".PHP_EOL; + } + + continue(2); + } else if ($this->tokens[$x]['line'] < $this->tokens[$i]['line']) { + break; + } + } + + // The string to the left of the colon is either a property or label. + for ($label = ($i - 1); $label >= 0; $label--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$label]['code']]) === false) { + break; + } + } + + if ($this->tokens[$label]['code'] !== T_STRING + && $this->tokens[$label]['code'] !== T_CONSTANT_ENCAPSED_STRING + ) { + continue; + } + + if (empty($classStack) === false) { + $this->tokens[$label]['code'] = T_PROPERTY; + $this->tokens[$label]['type'] = 'T_PROPERTY'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $label converted from T_STRING to T_PROPERTY *".PHP_EOL; + } + } else { + $this->tokens[$label]['code'] = T_LABEL; + $this->tokens[$label]['type'] = 'T_LABEL'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $label converted from T_STRING to T_LABEL *".PHP_EOL; + } + }//end if + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END ADDITIONAL JS PROCESSING ***".PHP_EOL; + } + + }//end processAdditional() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/PHP.php b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/PHP.php new file mode 100644 index 000000000..63fbcc48a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/PHP.php @@ -0,0 +1,3484 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Util; + +class PHP extends Tokenizer +{ + + /** + * A list of tokens that are allowed to open a scope. + * + * This array also contains information about what kind of token the scope + * opener uses to open and close the scope, if the token strictly requires + * an opener, if the token can share a scope closer, and who it can be shared + * with. An example of a token that shares a scope closer is a CASE scope. + * + * @var array + */ + public $scopeOpeners = [ + T_IF => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + ], + T_TRY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FINALLY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ELSE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + ], + ], + T_ELSEIF => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_IF => T_IF, + T_ELSE => T_ELSE, + ], + ], + T_FOR => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDFOR => T_ENDFOR, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_FOREACH => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDFOREACH => T_ENDFOREACH, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_INTERFACE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FUNCTION => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CLASS => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_TRAIT => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ENUM => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_USE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DECLARE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDDECLARE => T_ENDDECLARE, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_NAMESPACE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_WHILE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDWHILE => T_ENDWHILE, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DO => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_SWITCH => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDSWITCH => T_ENDSWITCH, + ], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CASE => [ + 'start' => [ + T_COLON => T_COLON, + T_SEMICOLON => T_SEMICOLON, + ], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_DEFAULT => T_DEFAULT, + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_DEFAULT => [ + 'start' => [ + T_COLON => T_COLON, + T_SEMICOLON => T_SEMICOLON, + ], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_MATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_START_HEREDOC => [ + 'start' => [T_START_HEREDOC => T_START_HEREDOC], + 'end' => [T_END_HEREDOC => T_END_HEREDOC], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_START_NOWDOC => [ + 'start' => [T_START_NOWDOC => T_START_NOWDOC], + 'end' => [T_END_NOWDOC => T_END_NOWDOC], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + ]; + + /** + * A list of tokens that end the scope. + * + * This array is just a unique collection of the end tokens + * from the scopeOpeners array. The data is duplicated here to + * save time during parsing of the file. + * + * @var array + */ + public $endScopeTokens = [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ENDFOR => T_ENDFOR, + T_ENDFOREACH => T_ENDFOREACH, + T_ENDWHILE => T_ENDWHILE, + T_ENDSWITCH => T_ENDSWITCH, + T_ENDDECLARE => T_ENDDECLARE, + T_BREAK => T_BREAK, + T_END_HEREDOC => T_END_HEREDOC, + T_END_NOWDOC => T_END_NOWDOC, + ]; + + /** + * Known lengths of tokens. + * + * @var array + */ + public $knownLengths = [ + T_ABSTRACT => 8, + T_AND_EQUAL => 2, + T_ARRAY => 5, + T_AS => 2, + T_BOOLEAN_AND => 2, + T_BOOLEAN_OR => 2, + T_BREAK => 5, + T_CALLABLE => 8, + T_CASE => 4, + T_CATCH => 5, + T_CLASS => 5, + T_CLASS_C => 9, + T_CLONE => 5, + T_CONCAT_EQUAL => 2, + T_CONST => 5, + T_CONTINUE => 8, + T_CURLY_OPEN => 2, + T_DEC => 2, + T_DECLARE => 7, + T_DEFAULT => 7, + T_DIR => 7, + T_DIV_EQUAL => 2, + T_DO => 2, + T_DOLLAR_OPEN_CURLY_BRACES => 2, + T_DOUBLE_ARROW => 2, + T_DOUBLE_COLON => 2, + T_ECHO => 4, + T_ELLIPSIS => 3, + T_ELSE => 4, + T_ELSEIF => 6, + T_EMPTY => 5, + T_ENDDECLARE => 10, + T_ENDFOR => 6, + T_ENDFOREACH => 10, + T_ENDIF => 5, + T_ENDSWITCH => 9, + T_ENDWHILE => 8, + T_ENUM => 4, + T_ENUM_CASE => 4, + T_EVAL => 4, + T_EXTENDS => 7, + T_FILE => 8, + T_FINAL => 5, + T_FINALLY => 7, + T_FN => 2, + T_FOR => 3, + T_FOREACH => 7, + T_FUNCTION => 8, + T_FUNC_C => 12, + T_GLOBAL => 6, + T_GOTO => 4, + T_HALT_COMPILER => 15, + T_IF => 2, + T_IMPLEMENTS => 10, + T_INC => 2, + T_INCLUDE => 7, + T_INCLUDE_ONCE => 12, + T_INSTANCEOF => 10, + T_INSTEADOF => 9, + T_INTERFACE => 9, + T_ISSET => 5, + T_IS_EQUAL => 2, + T_IS_GREATER_OR_EQUAL => 2, + T_IS_IDENTICAL => 3, + T_IS_NOT_EQUAL => 2, + T_IS_NOT_IDENTICAL => 3, + T_IS_SMALLER_OR_EQUAL => 2, + T_LINE => 8, + T_LIST => 4, + T_LOGICAL_AND => 3, + T_LOGICAL_OR => 2, + T_LOGICAL_XOR => 3, + T_MATCH => 5, + T_MATCH_ARROW => 2, + T_MATCH_DEFAULT => 7, + T_METHOD_C => 10, + T_MINUS_EQUAL => 2, + T_POW_EQUAL => 3, + T_MOD_EQUAL => 2, + T_MUL_EQUAL => 2, + T_NAMESPACE => 9, + T_NS_C => 13, + T_NS_SEPARATOR => 1, + T_NEW => 3, + T_NULLSAFE_OBJECT_OPERATOR => 3, + T_OBJECT_OPERATOR => 2, + T_OPEN_TAG_WITH_ECHO => 3, + T_OR_EQUAL => 2, + T_PLUS_EQUAL => 2, + T_PRINT => 5, + T_PRIVATE => 7, + T_PUBLIC => 6, + T_PROTECTED => 9, + T_READONLY => 8, + T_REQUIRE => 7, + T_REQUIRE_ONCE => 12, + T_RETURN => 6, + T_STATIC => 6, + T_SWITCH => 6, + T_THROW => 5, + T_TRAIT => 5, + T_TRAIT_C => 9, + T_TRY => 3, + T_UNSET => 5, + T_USE => 3, + T_VAR => 3, + T_WHILE => 5, + T_XOR_EQUAL => 2, + T_YIELD => 5, + T_OPEN_CURLY_BRACKET => 1, + T_CLOSE_CURLY_BRACKET => 1, + T_OPEN_SQUARE_BRACKET => 1, + T_CLOSE_SQUARE_BRACKET => 1, + T_OPEN_PARENTHESIS => 1, + T_CLOSE_PARENTHESIS => 1, + T_COLON => 1, + T_STRING_CONCAT => 1, + T_INLINE_THEN => 1, + T_INLINE_ELSE => 1, + T_NULLABLE => 1, + T_NULL => 4, + T_FALSE => 5, + T_TRUE => 4, + T_SEMICOLON => 1, + T_EQUAL => 1, + T_MULTIPLY => 1, + T_DIVIDE => 1, + T_PLUS => 1, + T_MINUS => 1, + T_MODULUS => 1, + T_POW => 2, + T_SPACESHIP => 3, + T_COALESCE => 2, + T_COALESCE_EQUAL => 3, + T_BITWISE_AND => 1, + T_BITWISE_OR => 1, + T_BITWISE_XOR => 1, + T_SL => 2, + T_SR => 2, + T_SL_EQUAL => 3, + T_SR_EQUAL => 3, + T_GREATER_THAN => 1, + T_LESS_THAN => 1, + T_BOOLEAN_NOT => 1, + T_SELF => 4, + T_PARENT => 6, + T_COMMA => 1, + T_THIS => 4, + T_CLOSURE => 8, + T_BACKTICK => 1, + T_OPEN_SHORT_ARRAY => 1, + T_CLOSE_SHORT_ARRAY => 1, + T_TYPE_UNION => 1, + T_TYPE_INTERSECTION => 1, + ]; + + /** + * Contexts in which keywords should always be tokenized as T_STRING. + * + * @var array + */ + protected $tstringContexts = [ + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_FUNCTION => true, + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_ENUM_CASE => true, + T_EXTENDS => true, + T_IMPLEMENTS => true, + T_ATTRIBUTE => true, + T_NEW => true, + T_CONST => true, + T_NS_SEPARATOR => true, + T_USE => true, + T_NAMESPACE => true, + T_PAAMAYIM_NEKUDOTAYIM => true, + ]; + + /** + * A cache of different token types, resolved into arrays. + * + * @var array + * @see standardiseToken() + */ + private static $resolveTokenCache = []; + + + /** + * Creates an array of tokens when given some PHP code. + * + * Starts by using token_get_all() but does a lot of extra processing + * to insert information about the context of the token. + * + * @param string $string The string to tokenize. + * + * @return array + */ + protected function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START PHP TOKENIZING ***".PHP_EOL; + $isWin = false; + if (stripos(PHP_OS, 'WIN') === 0) { + $isWin = true; + } + } + + $tokens = @token_get_all($string); + $finalTokens = []; + + $newStackPtr = 0; + $numTokens = count($tokens); + $lastNotEmptyToken = 0; + + $insideInlineIf = []; + $insideUseGroup = false; + + $commentTokenizer = new Comment(); + + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + // Special case for tokens we have needed to blank out. + if ($tokens[$stackPtr] === null) { + continue; + } + + $token = (array) $tokens[$stackPtr]; + $tokenIsArray = isset($token[1]); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($tokenIsArray === true) { + $type = Util\Tokens::tokenName($token[0]); + $content = Util\Common::prepareForOutput($token[1]); + } else { + $newToken = self::resolveSimpleToken($token[0]); + $type = $newToken['type']; + $content = Util\Common::prepareForOutput($token[0]); + } + + echo "\tProcess token "; + if ($tokenIsArray === true) { + echo "[$stackPtr]"; + } else { + echo " $stackPtr "; + } + + echo ": $type => $content"; + }//end if + + if ($newStackPtr > 0 + && isset(Util\Tokens::$emptyTokens[$finalTokens[($newStackPtr - 1)]['code']]) === false + ) { + $lastNotEmptyToken = ($newStackPtr - 1); + } + + /* + If we are using \r\n newline characters, the \r and \n are sometimes + split over two tokens. This normally occurs after comments. We need + to merge these two characters together so that our line endings are + consistent for all lines. + */ + + if ($tokenIsArray === true && substr($token[1], -1) === "\r") { + if (isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][1][0] === "\n" + ) { + $token[1] .= "\n"; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($isWin === true) { + echo '\n'; + } else { + echo "\033[30;1m\\n\033[0m"; + } + } + + if ($tokens[($stackPtr + 1)][1] === "\n") { + // This token's content has been merged into the previous, + // so we can skip it. + $tokens[($stackPtr + 1)] = ''; + } else { + $tokens[($stackPtr + 1)][1] = substr($tokens[($stackPtr + 1)][1], 1); + } + } + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + + /* + Tokenize context sensitive keyword as string when it should be string. + */ + + if ($tokenIsArray === true + && isset(Util\Tokens::$contextSensitiveKeywords[$token[0]]) === true + && (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + || $finalTokens[$lastNotEmptyToken]['content'] === '&') + ) { + if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true) { + $preserveKeyword = false; + + // `new class`, and `new static` should be preserved. + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && ($token[0] === T_CLASS + || $token[0] === T_STATIC) + ) { + $preserveKeyword = true; + } + + // `new class extends` `new class implements` should be preserved + if (($token[0] === T_EXTENDS || $token[0] === T_IMPLEMENTS) + && $finalTokens[$lastNotEmptyToken]['code'] === T_CLASS + ) { + $preserveKeyword = true; + } + + // `namespace\` should be preserved + if ($token[0] === T_NAMESPACE) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false) { + break; + } + + if (isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === true) { + continue; + } + + if ($tokens[$i][0] === T_NS_SEPARATOR) { + $preserveKeyword = true; + } + + break; + } + } + }//end if + + if ($finalTokens[$lastNotEmptyToken]['content'] === '&') { + $preserveKeyword = true; + + for ($i = ($lastNotEmptyToken - 1); $i >= 0; $i--) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$i]['code']]) === true) { + continue; + } + + if ($finalTokens[$i]['code'] === T_FUNCTION) { + $preserveKeyword = false; + } + + break; + } + } + + if ($preserveKeyword === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($token[0]); + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $token[1], + ]; + + $newStackPtr++; + continue; + } + }//end if + + /* + Parse doc blocks into something that can be easily iterated over. + */ + + if ($tokenIsArray === true + && ($token[0] === T_DOC_COMMENT + || ($token[0] === T_COMMENT && strpos($token[1], '/**') === 0)) + ) { + $commentTokens = $commentTokenizer->tokenizeString($token[1], $this->eolChar, $newStackPtr); + foreach ($commentTokens as $commentToken) { + $finalTokens[$newStackPtr] = $commentToken; + $newStackPtr++; + } + + continue; + } + + /* + PHP 8 tokenizes a new line after a slash and hash comment to the next whitespace token. + */ + + if (PHP_VERSION_ID >= 80000 + && $tokenIsArray === true + && ($token[0] === T_COMMENT && (strpos($token[1], '//') === 0 || strpos($token[1], '#') === 0)) + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + ) { + $nextToken = $tokens[($stackPtr + 1)]; + + // If the next token is a single new line, merge it into the comment token + // and set to it up to be skipped. + if ($nextToken[1] === "\n" || $nextToken[1] === "\r\n" || $nextToken[1] === "\n\r") { + $token[1] .= $nextToken[1]; + $tokens[($stackPtr + 1)] = null; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* merged newline after comment into comment token $stackPtr".PHP_EOL; + } + } else { + // This may be a whitespace token consisting of multiple new lines. + if (strpos($nextToken[1], "\r\n") === 0) { + $token[1] .= "\r\n"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 2); + } else if (strpos($nextToken[1], "\n\r") === 0) { + $token[1] .= "\n\r"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 2); + } else if (strpos($nextToken[1], "\n") === 0) { + $token[1] .= "\n"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 1); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* stripped first newline after comment and added it to comment token $stackPtr".PHP_EOL; + } + }//end if + }//end if + + /* + For Explicit Octal Notation prior to PHP 8.1 we need to combine the + T_LNUMBER and T_STRING token values into a single token value, and + then ignore the T_STRING token. + */ + + if (PHP_VERSION_ID < 80100 + && $tokenIsArray === true && $token[1] === '0' + && (isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_STRING + && strtolower($tokens[($stackPtr + 1)][1][0]) === 'o' + && $tokens[($stackPtr + 1)][1][1] !== '_') + && preg_match('`^(o[0-7]+(?:_[0-7]+)?)([0-9_]*)$`i', $tokens[($stackPtr + 1)][1], $matches) === 1 + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_LNUMBER, + 'type' => 'T_LNUMBER', + 'content' => $token[1] .= $matches[1], + ]; + $newStackPtr++; + + if (isset($matches[2]) === true && $matches[2] !== '') { + $type = 'T_LNUMBER'; + if ($matches[2][0] === '_') { + $type = 'T_STRING'; + } + + $finalTokens[$newStackPtr] = [ + 'code' => constant($type), + 'type' => $type, + 'content' => $matches[2], + ]; + $newStackPtr++; + } + + $stackPtr++; + continue; + }//end if + + /* + PHP 8.1 introduced two dedicated tokens for the & character. + Retokenizing both of these to T_BITWISE_AND, which is the + token PHPCS already tokenized them as. + */ + + if ($tokenIsArray === true + && ($token[0] === T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + || $token[0] === T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG) + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BITWISE_AND, + 'type' => 'T_BITWISE_AND', + 'content' => $token[1], + ]; + $newStackPtr++; + continue; + } + + /* + If this is a double quoted string, PHP will tokenize the whole + thing which causes problems with the scope map when braces are + within the string. So we need to merge the tokens together to + provide a single string. + */ + + if ($tokenIsArray === false && ($token[0] === '"' || $token[0] === 'b"')) { + // Binary casts need a special token. + if ($token[0] === 'b"') { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => 'b', + ]; + $newStackPtr++; + } + + $tokenContent = '"'; + $nestedVars = []; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + $subToken = (array) $tokens[$i]; + $subTokenIsArray = isset($subToken[1]); + + if ($subTokenIsArray === true) { + $tokenContent .= $subToken[1]; + if (($subToken[1] === '{' + || $subToken[1] === '${') + && $subToken[0] !== T_ENCAPSED_AND_WHITESPACE + ) { + $nestedVars[] = $i; + } + } else { + $tokenContent .= $subToken[0]; + if ($subToken[0] === '}') { + array_pop($nestedVars); + } + } + + if ($subTokenIsArray === false + && $subToken[0] === '"' + && empty($nestedVars) === true + ) { + // We found the other end of the double quoted string. + break; + } + }//end for + + $stackPtr = $i; + + // Convert each line within the double quoted string to a + // new token, so it conforms with other multiple line tokens. + $tokenLines = explode($this->eolChar, $tokenContent); + $numLines = count($tokenLines); + $newToken = []; + + for ($j = 0; $j < $numLines; $j++) { + $newToken['content'] = $tokenLines[$j]; + if ($j === ($numLines - 1)) { + if ($tokenLines[$j] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $newToken['code'] = T_DOUBLE_QUOTED_STRING; + $newToken['type'] = 'T_DOUBLE_QUOTED_STRING'; + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + + // Continue, as we're done with this token. + continue; + }//end if + + /* + Detect binary casting and assign the casts their own token. + */ + + if ($tokenIsArray === true + && $token[0] === T_CONSTANT_ENCAPSED_STRING + && (substr($token[1], 0, 2) === 'b"' + || substr($token[1], 0, 2) === "b'") + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => 'b', + ]; + $newStackPtr++; + $token[1] = substr($token[1], 1); + } + + if ($tokenIsArray === true + && $token[0] === T_STRING_CAST + && preg_match('`^\(\s*binary\s*\)$`i', $token[1]) === 1 + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => $token[1], + ]; + $newStackPtr++; + continue; + } + + /* + If this is a heredoc, PHP will tokenize the whole + thing which causes problems when heredocs don't + contain real PHP code, which is almost never. + We want to leave the start and end heredoc tokens + alone though. + */ + + if ($tokenIsArray === true && $token[0] === T_START_HEREDOC) { + // Add the start heredoc token to the final array. + $finalTokens[$newStackPtr] = self::standardiseToken($token); + + // Check if this is actually a nowdoc and use a different token + // to help the sniffs. + $nowdoc = false; + if (strpos($token[1], "'") !== false) { + $finalTokens[$newStackPtr]['code'] = T_START_NOWDOC; + $finalTokens[$newStackPtr]['type'] = 'T_START_NOWDOC'; + $nowdoc = true; + } + + $tokenContent = ''; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + $subTokenIsArray = is_array($tokens[$i]); + if ($subTokenIsArray === true + && $tokens[$i][0] === T_END_HEREDOC + ) { + // We found the other end of the heredoc. + break; + } + + if ($subTokenIsArray === true) { + $tokenContent .= $tokens[$i][1]; + } else { + $tokenContent .= $tokens[$i]; + } + } + + if ($i === $numTokens) { + // We got to the end of the file and never + // found the closing token, so this probably wasn't + // a heredoc. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $finalTokens[$newStackPtr]['type']; + echo "\t\t* failed to find the end of the here/nowdoc".PHP_EOL; + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr]['code'] = T_STRING; + $finalTokens[$newStackPtr]['type'] = 'T_STRING'; + $newStackPtr++; + continue; + } + + $stackPtr = $i; + $newStackPtr++; + + // Convert each line within the heredoc to a + // new token, so it conforms with other multiple line tokens. + $tokenLines = explode($this->eolChar, $tokenContent); + $numLines = count($tokenLines); + $newToken = []; + + for ($j = 0; $j < $numLines; $j++) { + $newToken['content'] = $tokenLines[$j]; + if ($j === ($numLines - 1)) { + if ($tokenLines[$j] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + if ($nowdoc === true) { + $newToken['code'] = T_NOWDOC; + $newToken['type'] = 'T_NOWDOC'; + } else { + $newToken['code'] = T_HEREDOC; + $newToken['type'] = 'T_HEREDOC'; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + }//end for + + // Add the end heredoc token to the final array. + $finalTokens[$newStackPtr] = self::standardiseToken($tokens[$stackPtr]); + + if ($nowdoc === true) { + $finalTokens[$newStackPtr]['code'] = T_END_NOWDOC; + $finalTokens[$newStackPtr]['type'] = 'T_END_NOWDOC'; + } + + $newStackPtr++; + + // Continue, as we're done with this token. + continue; + }//end if + + /* + Enum keyword for PHP < 8.1 + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'enum' + ) { + // Get the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (isset($tokens[$i]) === true + && is_array($tokens[$i]) === true + && $tokens[$i][0] === T_STRING + ) { + // Modify $tokens directly so we can use it later when converting enum "case". + $tokens[$stackPtr][0] = T_ENUM; + + $newToken = []; + $newToken['code'] = T_ENUM; + $newToken['type'] = 'T_ENUM'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_ENUM".PHP_EOL; + } + + $newStackPtr++; + continue; + } + }//end if + + /* + Convert enum "case" to T_ENUM_CASE + */ + + if ($tokenIsArray === true + && $token[0] === T_CASE + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + $isEnumCase = false; + $scope = 1; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i] === '}') { + $scope++; + continue; + } + + if ($tokens[$i] === '{') { + $scope--; + continue; + } + + if (is_array($tokens[$i]) === false) { + continue; + } + + if ($scope !== 0) { + continue; + } + + if ($tokens[$i][0] === T_SWITCH) { + break; + } + + if ($tokens[$i][0] === T_ENUM || $tokens[$i][0] === T_ENUM_CASE) { + $isEnumCase = true; + break; + } + }//end for + + if ($isEnumCase === true) { + // Modify $tokens directly so we can use it as optimisation for other enum "case". + $tokens[$stackPtr][0] = T_ENUM_CASE; + + $newToken = []; + $newToken['code'] = T_ENUM_CASE; + $newToken['type'] = 'T_ENUM_CASE'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_CASE to T_ENUM_CASE".PHP_EOL; + } + + $newStackPtr++; + continue; + } + }//end if + + /* + As of PHP 8.0 fully qualified, partially qualified and namespace relative + identifier names are tokenized differently. + This "undoes" the new tokenization so the tokenization will be the same in + in PHP 5, 7 and 8. + */ + + if (PHP_VERSION_ID >= 80000 + && $tokenIsArray === true + && ($token[0] === T_NAME_QUALIFIED + || $token[0] === T_NAME_FULLY_QUALIFIED + || $token[0] === T_NAME_RELATIVE) + ) { + $name = $token[1]; + + if ($token[0] === T_NAME_FULLY_QUALIFIED) { + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $name = ltrim($name, '\\'); + } + + if ($token[0] === T_NAME_RELATIVE) { + $newToken = []; + $newToken['code'] = T_NAMESPACE; + $newToken['type'] = 'T_NAMESPACE'; + $newToken['content'] = substr($name, 0, 9); + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $name = substr($name, 10); + } + + $parts = explode('\\', $name); + $partCount = count($parts); + $lastPart = ($partCount - 1); + + foreach ($parts as $i => $part) { + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $part; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + if ($i !== $lastPart) { + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($token[0]); + $content = Util\Common::prepareForOutput($token[1]); + echo "\t\t* token $stackPtr split into individual tokens; was: $type => $content".PHP_EOL; + } + + continue; + }//end if + + /* + PHP 8.0 Attributes + */ + + if (PHP_VERSION_ID < 80000 + && $token[0] === T_COMMENT + && strpos($token[1], '#[') === 0 + ) { + $subTokens = $this->parsePhpAttribute($tokens, $stackPtr); + if ($subTokens !== null) { + array_splice($tokens, $stackPtr, 1, $subTokens); + $numTokens = count($tokens); + + $tokenIsArray = true; + $token = $tokens[$stackPtr]; + } else { + $token[0] = T_ATTRIBUTE; + } + } + + if ($tokenIsArray === true + && $token[0] === T_ATTRIBUTE + ) { + // Go looking for the close bracket. + $bracketCloser = $this->findCloser($tokens, ($stackPtr + 1), ['[', '#['], ']'); + + $newToken = []; + $newToken['code'] = T_ATTRIBUTE; + $newToken['type'] = 'T_ATTRIBUTE'; + $newToken['content'] = '#['; + $finalTokens[$newStackPtr] = $newToken; + + $tokens[$bracketCloser] = []; + $tokens[$bracketCloser][0] = T_ATTRIBUTE_END; + $tokens[$bracketCloser][1] = ']'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $bracketCloser changed from T_CLOSE_SQUARE_BRACKET to T_ATTRIBUTE_END".PHP_EOL; + } + + $newStackPtr++; + continue; + }//end if + + /* + Tokenize the parameter labels for PHP 8.0 named parameters as a special T_PARAM_NAME + token and ensure that the colon after it is always T_COLON. + */ + + if ($tokenIsArray === true + && ($token[0] === T_STRING + || preg_match('`^[a-zA-Z_\x80-\xff]`', $token[1]) === 1) + ) { + // Get the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (isset($tokens[$i]) === true + && is_array($tokens[$i]) === false + && $tokens[$i] === ':' + ) { + // Get the previous non-empty token. + for ($j = ($stackPtr - 1); $j > 0; $j--) { + if (is_array($tokens[$j]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$j][0]]) === false + ) { + break; + } + } + + if (is_array($tokens[$j]) === false + && ($tokens[$j] === '(' + || $tokens[$j] === ',') + ) { + $newToken = []; + $newToken['code'] = T_PARAM_NAME; + $newToken['type'] = 'T_PARAM_NAME'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + + // Modify the original token stack so that future checks, like + // determining T_COLON vs T_INLINE_ELSE can handle this correctly. + $tokens[$stackPtr][0] = T_PARAM_NAME; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($token[0]); + echo "\t\t* token $stackPtr changed from $type to T_PARAM_NAME".PHP_EOL; + } + + continue; + } + }//end if + }//end if + + /* + "readonly" keyword for PHP < 8.1 + */ + + if (PHP_VERSION_ID < 80100 + && $tokenIsArray === true + && strtolower($token[1]) === 'readonly' + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + // Get the next non-whitespace token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || $tokens[$i][0] !== T_WHITESPACE + ) { + break; + } + } + + if (isset($tokens[$i]) === false + || $tokens[$i] !== '(' + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_READONLY, + 'type' => 'T_READONLY', + 'content' => $token[1], + ]; + $newStackPtr++; + + continue; + } + }//end if + + /* + Before PHP 7.0, the "yield from" was tokenized as + T_YIELD, T_WHITESPACE and T_STRING. So look for + and change this token in earlier versions. + */ + + if (PHP_VERSION_ID < 70000 + && PHP_VERSION_ID >= 50500 + && $tokenIsArray === true + && $token[0] === T_YIELD + && isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + && $tokens[($stackPtr + 2)][0] === T_STRING + && strtolower($tokens[($stackPtr + 2)][1]) === 'from' + ) { + // Could be multi-line, so adjust the token stack. + $token[0] = T_YIELD_FROM; + $token[1] .= $tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) { + $type = Util\Tokens::tokenName($tokens[$i][0]); + $content = Util\Common::prepareForOutput($tokens[$i][1]); + echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL; + } + } + + $tokens[($stackPtr + 1)] = null; + $tokens[($stackPtr + 2)] = null; + } + + /* + Before PHP 5.5, the yield keyword was tokenized as + T_STRING. So look for and change this token in + earlier versions. + Checks also if it is just "yield" or "yield from". + */ + + if (PHP_VERSION_ID < 50500 + && $tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'yield' + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + if (isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + && $tokens[($stackPtr + 2)][0] === T_STRING + && strtolower($tokens[($stackPtr + 2)][1]) === 'from' + ) { + // Could be multi-line, so just just the token stack. + $token[0] = T_YIELD_FROM; + $token[1] .= $tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) { + $type = Util\Tokens::tokenName($tokens[$i][0]); + $content = Util\Common::prepareForOutput($tokens[$i][1]); + echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL; + } + } + + $tokens[($stackPtr + 1)] = null; + $tokens[($stackPtr + 2)] = null; + } else { + $newToken = []; + $newToken['code'] = T_YIELD; + $newToken['type'] = 'T_YIELD'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Before PHP 5.6, the ... operator was tokenized as three + T_STRING_CONCAT tokens in a row. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '.' + && isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)] === '.' + && $tokens[($stackPtr + 2)] === '.' + ) { + $newToken = []; + $newToken['code'] = T_ELLIPSIS; + $newToken['type'] = 'T_ELLIPSIS'; + $newToken['content'] = '...'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr += 2; + continue; + } + + /* + Before PHP 5.6, the ** operator was tokenized as two + T_MULTIPLY tokens in a row. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '*' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)] === '*' + ) { + $newToken = []; + $newToken['code'] = T_POW; + $newToken['type'] = 'T_POW'; + $newToken['content'] = '**'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 5.6, the **= operator was tokenized as + T_MULTIPLY followed by T_MUL_EQUAL. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '*' + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][1] === '*=' + ) { + $newToken = []; + $newToken['code'] = T_POW_EQUAL; + $newToken['type'] = 'T_POW_EQUAL'; + $newToken['content'] = '**='; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 7, the ??= operator was tokenized as + T_INLINE_THEN, T_INLINE_THEN, T_EQUAL. + Between PHP 7.0 and 7.3, the ??= operator was tokenized as + T_COALESCE, T_EQUAL. + So look for and combine these tokens in earlier versions. + */ + + if (($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '?' + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 2)][0] === '=') + || ($tokenIsArray === true + && $token[0] === T_COALESCE + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '=') + ) { + $newToken = []; + $newToken['code'] = T_COALESCE_EQUAL; + $newToken['type'] = 'T_COALESCE_EQUAL'; + $newToken['content'] = '??='; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + + if ($tokenIsArray === false) { + // Pre PHP 7. + $stackPtr++; + } + + continue; + } + + /* + Before PHP 7, the ?? operator was tokenized as + T_INLINE_THEN followed by T_INLINE_THEN. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '?' + ) { + $newToken = []; + $newToken['code'] = T_COALESCE; + $newToken['type'] = 'T_COALESCE'; + $newToken['content'] = '??'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 8, the ?-> operator was tokenized as + T_INLINE_THEN followed by T_OBJECT_OPERATOR. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_OBJECT_OPERATOR + ) { + $newToken = []; + $newToken['code'] = T_NULLSAFE_OBJECT_OPERATOR; + $newToken['type'] = 'T_NULLSAFE_OBJECT_OPERATOR'; + $newToken['content'] = '?->'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 7.4, underscores inside T_LNUMBER and T_DNUMBER + tokens split the token with a T_STRING. So look for + and change these tokens in earlier versions. + */ + + if (PHP_VERSION_ID < 70400 + && ($tokenIsArray === true + && ($token[0] === T_LNUMBER + || $token[0] === T_DNUMBER) + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_STRING + && $tokens[($stackPtr + 1)][1][0] === '_') + ) { + $newContent = $token[1]; + $newType = $token[0]; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false) { + break; + } + + if ($tokens[$i][0] === T_LNUMBER + || $tokens[$i][0] === T_DNUMBER + ) { + $newContent .= $tokens[$i][1]; + continue; + } + + if ($tokens[$i][0] === T_STRING + && $tokens[$i][1][0] === '_' + && ((strpos($newContent, '0x') === 0 + && preg_match('`^((? PHP_INT_MAX) + || (stripos($newContent, '0b') === 0 && bindec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (stripos($newContent, '0o') === 0 && octdec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (stripos($newContent, '0x') !== 0 + && stripos($newContent, 'e') !== false || strpos($newContent, '.') !== false) + || (strpos($newContent, '0') === 0 && stripos($newContent, '0x') !== 0 + && stripos($newContent, '0b') !== 0 && octdec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (strpos($newContent, '0') !== 0 && str_replace('_', '', $newContent) > PHP_INT_MAX)) + ) { + $newType = T_DNUMBER; + } + + $newToken = []; + $newToken['code'] = $newType; + $newToken['type'] = Util\Tokens::tokenName($newType); + $newToken['content'] = $newContent; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr = ($i - 1); + continue; + }//end if + + /* + Backfill the T_MATCH token for PHP versions < 8.0 and + do initial correction for non-match expression T_MATCH tokens + to T_STRING for PHP >= 8.0. + A final check for non-match expression T_MATCH tokens is done + in PHP::processAdditional(). + */ + + if ($tokenIsArray === true + && (($token[0] === T_STRING + && strtolower($token[1]) === 'match') + || $token[0] === T_MATCH) + ) { + $isMatch = false; + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (isset($tokens[$x][0], Util\Tokens::$emptyTokens[$tokens[$x][0]]) === true) { + continue; + } + + if ($tokens[$x] !== '(') { + // This is not a match expression. + break; + } + + if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true) { + // Also not a match expression. + break; + } + + $isMatch = true; + break; + }//end for + + if ($isMatch === true && $token[0] === T_STRING) { + $newToken = []; + $newToken['code'] = T_MATCH; + $newToken['type'] = 'T_MATCH'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_MATCH".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + } else if ($isMatch === false && $token[0] === T_MATCH) { + // PHP 8.0, match keyword, but not a match expression. + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_MATCH to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Retokenize the T_DEFAULT in match control structures as T_MATCH_DEFAULT + to prevent scope being set and the scope for switch default statements + breaking. + */ + + if ($tokenIsArray === true + && $token[0] === T_DEFAULT + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if ($tokens[$x] === ',') { + // Skip over potential trailing comma (supported in PHP). + continue; + } + + if (is_array($tokens[$x]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === false + ) { + // Non-empty, non-comma content. + break; + } + } + + if (isset($tokens[$x]) === true + && is_array($tokens[$x]) === true + && $tokens[$x][0] === T_DOUBLE_ARROW + ) { + // Modify the original token stack for the double arrow so that + // future checks can disregard the double arrow token more easily. + // For match expression "case" statements, this is handled + // in PHP::processAdditional(). + $tokens[$x][0] = T_MATCH_ARROW; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + } + + $newToken = []; + $newToken['code'] = T_MATCH_DEFAULT; + $newToken['type'] = 'T_MATCH_DEFAULT'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Convert ? to T_NULLABLE OR T_INLINE_THEN + */ + + if ($tokenIsArray === false && $token[0] === '?') { + $newToken = []; + $newToken['content'] = '?'; + + /* + * Check if the next non-empty token is one of the tokens which can be used + * in type declarations. If not, it's definitely a ternary. + * At this point, the only token types which need to be taken into consideration + * as potential type declarations are identifier names, T_ARRAY, T_CALLABLE and T_NS_SEPARATOR. + */ + + $lastRelevantNonEmpty = null; + + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if (isset(Util\Tokens::$emptyTokens[$tokenType]) === true) { + continue; + } + + if ($tokenType === T_STRING + || $tokenType === T_NAME_FULLY_QUALIFIED + || $tokenType === T_NAME_RELATIVE + || $tokenType === T_NAME_QUALIFIED + || $tokenType === T_ARRAY + || $tokenType === T_NAMESPACE + || $tokenType === T_NS_SEPARATOR + ) { + $lastRelevantNonEmpty = $tokenType; + continue; + } + + if (($tokenType !== T_CALLABLE + && isset($lastRelevantNonEmpty) === false) + || ($lastRelevantNonEmpty === T_ARRAY + && $tokenType === '(') + || (($lastRelevantNonEmpty === T_STRING + || $lastRelevantNonEmpty === T_NAME_FULLY_QUALIFIED + || $lastRelevantNonEmpty === T_NAME_RELATIVE + || $lastRelevantNonEmpty === T_NAME_QUALIFIED) + && ($tokenType === T_DOUBLE_COLON + || $tokenType === '(' + || $tokenType === ':')) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + } + + $newToken['code'] = T_INLINE_THEN; + $newToken['type'] = 'T_INLINE_THEN'; + + $insideInlineIf[] = $stackPtr; + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue 2; + } + + break; + }//end for + + /* + * This can still be a nullable type or a ternary. + * Do additional checking. + */ + + $prevNonEmpty = null; + $lastSeenNonEmpty = null; + + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if ($tokenType === T_STATIC + && ($lastSeenNonEmpty === T_DOUBLE_COLON + || $lastSeenNonEmpty === '(') + ) { + $lastSeenNonEmpty = $tokenType; + continue; + } + + if ($prevNonEmpty === null + && isset(Util\Tokens::$emptyTokens[$tokenType]) === false + ) { + // Found the previous non-empty token. + if ($tokenType === ':' || $tokenType === ',' || $tokenType === T_ATTRIBUTE_END) { + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + break; + } + + $prevNonEmpty = $tokenType; + } + + if ($tokenType === T_FUNCTION + || $tokenType === T_FN + || isset(Util\Tokens::$methodPrefixes[$tokenType]) === true + || $tokenType === T_VAR + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + break; + } else if (in_array($tokenType, [T_DOUBLE_ARROW, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, '=', '{', ';'], true) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + } + + $newToken['code'] = T_INLINE_THEN; + $newToken['type'] = 'T_INLINE_THEN'; + + $insideInlineIf[] = $stackPtr; + break; + } + + if (isset(Util\Tokens::$emptyTokens[$tokenType]) === false) { + $lastSeenNonEmpty = $tokenType; + } + }//end for + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + + /* + Tokens after a double colon may look like scope openers, + such as when writing code like Foo::NAMESPACE, but they are + only ever variables or strings. + */ + + if ($stackPtr > 1 + && (is_array($tokens[($stackPtr - 1)]) === true + && $tokens[($stackPtr - 1)][0] === T_PAAMAYIM_NEKUDOTAYIM) + && $tokenIsArray === true + && $token[0] !== T_STRING + && $token[0] !== T_VARIABLE + && $token[0] !== T_DOLLAR + && isset(Util\Tokens::$emptyTokens[$token[0]]) === false + ) { + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + continue; + } + + /* + Backfill the T_FN token for PHP versions < 7.4. + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'fn' + ) { + // Modify the original token stack so that + // future checks (like looking for T_NULLABLE) can + // detect the T_FN token more easily. + $tokens[$stackPtr][0] = T_FN; + $token[0] = T_FN; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_FN".PHP_EOL; + } + } + + /* + This is a special condition for T_ARRAY tokens used for + function return types. We want to keep the parenthesis map clean, + so let's tag these tokens as T_STRING. + */ + + if ($tokenIsArray === true + && ($token[0] === T_FUNCTION + || $token[0] === T_FN) + && $finalTokens[$lastNotEmptyToken]['code'] !== T_USE + ) { + // Go looking for the colon to start the return type hint. + // Start by finding the closing parenthesis of the function. + $parenthesisStack = []; + $parenthesisCloser = false; + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false && $tokens[$x] === '(') { + $parenthesisStack[] = $x; + } else if (is_array($tokens[$x]) === false && $tokens[$x] === ')') { + array_pop($parenthesisStack); + if (empty($parenthesisStack) === true) { + $parenthesisCloser = $x; + break; + } + } + } + + if ($parenthesisCloser !== false) { + for ($x = ($parenthesisCloser + 1); $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === false + ) { + // Non-empty content. + if (is_array($tokens[$x]) === true && $tokens[$x][0] === T_USE) { + // Found a use statements, so search ahead for the closing parenthesis. + for ($x += 1; $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false && $tokens[$x] === ')') { + continue(2); + } + } + } + + break; + } + } + + if (isset($tokens[$x]) === true + && is_array($tokens[$x]) === false + && $tokens[$x] === ':' + ) { + // Find the start of the return type. + for ($x += 1; $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === true + && isset(Util\Tokens::$emptyTokens[$tokens[$x][0]]) === true + ) { + // Whitespace or comments before the return type. + continue; + } + + if (is_array($tokens[$x]) === false && $tokens[$x] === '?') { + // Found a nullable operator, so skip it. + // But also convert the token to save the tokenizer + // a bit of time later on. + $tokens[$x] = [ + T_NULLABLE, + '?', + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from ? to T_NULLABLE".PHP_EOL; + } + + continue; + } + + break; + }//end for + }//end if + }//end if + }//end if + + /* + Before PHP 7, the <=> operator was tokenized as + T_IS_SMALLER_OR_EQUAL followed by T_GREATER_THAN. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === true + && $token[0] === T_IS_SMALLER_OR_EQUAL + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '>' + ) { + $newToken = []; + $newToken['code'] = T_SPACESHIP; + $newToken['type'] = 'T_SPACESHIP'; + $newToken['content'] = '<=>'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + PHP doesn't assign a token to goto labels, so we have to. + These are just string tokens with a single colon after them. Double + colons are already tokenized and so don't interfere with this check. + But we do have to account for CASE statements, that look just like + goto labels. + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)] === ':' + && (is_array($tokens[($stackPtr - 1)]) === false + || $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM) + ) { + $stopTokens = [ + T_CASE => true, + T_SEMICOLON => true, + T_OPEN_TAG => true, + T_OPEN_CURLY_BRACKET => true, + T_INLINE_THEN => true, + T_ENUM => true, + ]; + + for ($x = ($newStackPtr - 1); $x > 0; $x--) { + if (isset($stopTokens[$finalTokens[$x]['code']]) === true) { + break; + } + } + + if ($finalTokens[$x]['code'] !== T_CASE + && $finalTokens[$x]['code'] !== T_INLINE_THEN + && $finalTokens[$x]['code'] !== T_ENUM + ) { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1].':', + 'code' => T_GOTO_LABEL, + 'type' => 'T_GOTO_LABEL', + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_GOTO_LABEL".PHP_EOL; + echo "\t\t* skipping T_COLON token ".($stackPtr + 1).PHP_EOL; + } + + $newStackPtr++; + $stackPtr++; + continue; + } + }//end if + + /* + If this token has newlines in its content, split each line up + and create a new token for each line. We do this so it's easier + to ascertain where errors occur on a line. + Note that $token[1] is the token's content. + */ + + if ($tokenIsArray === true && strpos($token[1], $this->eolChar) !== false) { + $tokenLines = explode($this->eolChar, $token[1]); + $numLines = count($tokenLines); + $newToken = [ + 'type' => Util\Tokens::tokenName($token[0]), + 'code' => $token[0], + 'content' => '', + ]; + + for ($i = 0; $i < $numLines; $i++) { + $newToken['content'] = $tokenLines[$i]; + if ($i === ($numLines - 1)) { + if ($tokenLines[$i] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + } else { + // Some T_STRING tokens should remain that way due to their context. + if ($tokenIsArray === true + && $token[0] === T_STRING + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + ) { + // Special case for syntax like: return new self/new parent + // where self/parent should not be a string. + $tokenContentLower = strtolower($token[1]); + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && ($tokenContentLower === 'self' || $tokenContentLower === 'parent') + ) { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1], + ]; + if ($tokenContentLower === 'self') { + $finalTokens[$newStackPtr]['code'] = T_SELF; + $finalTokens[$newStackPtr]['type'] = 'T_SELF'; + } + + if ($tokenContentLower === 'parent') { + $finalTokens[$newStackPtr]['code'] = T_PARENT; + $finalTokens[$newStackPtr]['type'] = 'T_PARENT'; + } + } else { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1], + 'code' => T_STRING, + 'type' => 'T_STRING', + ]; + } + + $newStackPtr++; + continue; + }//end if + + $newToken = null; + if ($tokenIsArray === false) { + if (isset(self::$resolveTokenCache[$token[0]]) === true) { + $newToken = self::$resolveTokenCache[$token[0]]; + } + } else { + $cacheKey = null; + if ($token[0] === T_STRING) { + $cacheKey = strtolower($token[1]); + } else if ($token[0] !== T_CURLY_OPEN) { + $cacheKey = $token[0]; + } + + if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) { + $newToken = self::$resolveTokenCache[$cacheKey]; + $newToken['content'] = $token[1]; + } + } + + if ($newToken === null) { + $newToken = self::standardiseToken($token); + } + + // Convert colons that are actually the ELSE component of an + // inline IF statement. + if (empty($insideInlineIf) === false && $newToken['code'] === T_COLON) { + $isInlineIf = true; + + // Make sure this isn't a named parameter label. + // Get the previous non-empty token. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if ($tokens[$i][0] === T_PARAM_NAME) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is parameter label, not T_INLINE_ELSE".PHP_EOL; + } + } + + if ($isInlineIf === true) { + // Make sure this isn't a return type separator. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || ($tokens[$i][0] !== T_DOC_COMMENT + && $tokens[$i][0] !== T_COMMENT + && $tokens[$i][0] !== T_WHITESPACE) + ) { + break; + } + } + + if ($tokens[$i] === ')') { + $parenCount = 1; + for ($i--; $i > 0; $i--) { + if ($tokens[$i] === '(') { + $parenCount--; + if ($parenCount === 0) { + break; + } + } else if ($tokens[$i] === ')') { + $parenCount++; + } + } + + // We've found the open parenthesis, so if the previous + // non-empty token is FUNCTION or USE, this is a return type. + // Note that we need to skip T_STRING tokens here as these + // can be function names. + for ($i--; $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || ($tokens[$i][0] !== T_DOC_COMMENT + && $tokens[$i][0] !== T_COMMENT + && $tokens[$i][0] !== T_WHITESPACE + && $tokens[$i][0] !== T_STRING) + ) { + break; + } + } + + if ($tokens[$i][0] === T_FUNCTION || $tokens[$i][0] === T_FN || $tokens[$i][0] === T_USE) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is return type, not T_INLINE_ELSE".PHP_EOL; + } + } + }//end if + }//end if + + // Check to see if this is a CASE or DEFAULT opener. + if ($isInlineIf === true) { + $inlineIfToken = $insideInlineIf[(count($insideInlineIf) - 1)]; + for ($i = $stackPtr; $i > $inlineIfToken; $i--) { + if (is_array($tokens[$i]) === true + && ($tokens[$i][0] === T_CASE + || $tokens[$i][0] === T_DEFAULT) + ) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is T_CASE or T_DEFAULT opener, not T_INLINE_ELSE".PHP_EOL; + } + + break; + } + + if (is_array($tokens[$i]) === false + && ($tokens[$i] === ';' + || $tokens[$i] === '{') + ) { + break; + } + } + }//end if + + if ($isInlineIf === true) { + array_pop($insideInlineIf); + $newToken['code'] = T_INLINE_ELSE; + $newToken['type'] = 'T_INLINE_ELSE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token changed from T_COLON to T_INLINE_ELSE".PHP_EOL; + } + } + }//end if + + // This is a special condition for T_ARRAY tokens used for anything else + // but array declarations, like type hinting function arguments as + // being arrays. + // We want to keep the parenthesis map clean, so let's tag these tokens as + // T_STRING. + if ($newToken['code'] === T_ARRAY) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Util\Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + // Non-empty content. + break; + } + } + + if ($i !== $numTokens && $tokens[$i] !== '(') { + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + } + } + + // This is a special case when checking PHP 5.5+ code in PHP < 5.5 + // where "finally" should be T_FINALLY instead of T_STRING. + if ($newToken['code'] === T_STRING + && strtolower($newToken['content']) === 'finally' + && $finalTokens[$lastNotEmptyToken]['code'] === T_CLOSE_CURLY_BRACKET + ) { + $newToken['code'] = T_FINALLY; + $newToken['type'] = 'T_FINALLY'; + } + + // This is a special case for PHP 5.6 use function and use const + // where "function" and "const" should be T_STRING instead of T_FUNCTION + // and T_CONST. + if (($newToken['code'] === T_FUNCTION + || $newToken['code'] === T_CONST) + && ($finalTokens[$lastNotEmptyToken]['code'] === T_USE || $insideUseGroup === true) + ) { + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + } + + // This is a special case for use groups in PHP 7+ where leaving + // the curly braces as their normal tokens would confuse + // the scope map and sniffs. + if ($newToken['code'] === T_OPEN_CURLY_BRACKET + && $finalTokens[$lastNotEmptyToken]['code'] === T_NS_SEPARATOR + ) { + $newToken['code'] = T_OPEN_USE_GROUP; + $newToken['type'] = 'T_OPEN_USE_GROUP'; + $insideUseGroup = true; + } + + if ($insideUseGroup === true && $newToken['code'] === T_CLOSE_CURLY_BRACKET) { + $newToken['code'] = T_CLOSE_USE_GROUP; + $newToken['type'] = 'T_CLOSE_USE_GROUP'; + $insideUseGroup = false; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END PHP TOKENIZING ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Performs additional processing after main tokenizing. + * + * This additional processing checks for CASE statements that are using curly + * braces for scope openers and closers. It also turns some T_FUNCTION tokens + * into T_CLOSURE when they are not standard function definitions. It also + * detects short array syntax and converts those square brackets into new tokens. + * It also corrects some usage of the static and class keywords. It also + * assigns tokens to function return types. + * + * @return void + */ + protected function processAdditional() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL; + } + + $this->createAttributesNestingMap(); + + $numTokens = count($this->tokens); + for ($i = ($numTokens - 1); $i >= 0; $i--) { + // Check for any unset scope conditions due to alternate IF/ENDIF syntax. + if (isset($this->tokens[$i]['scope_opener']) === true + && isset($this->tokens[$i]['scope_condition']) === false + ) { + $this->tokens[$i]['scope_condition'] = $this->tokens[$this->tokens[$i]['scope_opener']]['scope_condition']; + } + + if ($this->tokens[$i]['code'] === T_FUNCTION) { + /* + Detect functions that are actually closures and + assign them a different token. + */ + + if (isset($this->tokens[$i]['scope_opener']) === true) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false + && $this->tokens[$x]['code'] !== T_BITWISE_AND + ) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$i]['code'] = T_CLOSURE; + $this->tokens[$i]['type'] = 'T_CLOSURE'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL; + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_CLOSURE; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_CLASS && isset($this->tokens[$i]['scope_opener']) === true) { + /* + Detect anonymous classes and assign them a different token. + */ + + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + || $this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET + || $this->tokens[$x]['code'] === T_EXTENDS + || $this->tokens[$x]['code'] === T_IMPLEMENTS + ) { + $this->tokens[$i]['code'] = T_ANON_CLASS; + $this->tokens[$i]['type'] = 'T_ANON_CLASS'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL; + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + && isset($this->tokens[$x]['parenthesis_closer']) === true + ) { + $closer = $this->tokens[$x]['parenthesis_closer']; + + $this->tokens[$i]['parenthesis_opener'] = $x; + $this->tokens[$i]['parenthesis_closer'] = $closer; + $this->tokens[$i]['parenthesis_owner'] = $i; + $this->tokens[$x]['parenthesis_owner'] = $i; + $this->tokens[$closer]['parenthesis_owner'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t\t* added parenthesis keys to T_ANON_CLASS token $i on line $line".PHP_EOL; + } + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_ANON_CLASS; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_FN && isset($this->tokens[($i + 1)]) === true) { + // Possible arrow function. + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false + && $this->tokens[$x]['code'] !== T_BITWISE_AND + ) { + // Non-whitespace content. + break; + } + } + + if (isset($this->tokens[$x]) === true && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $ignore = Util\Tokens::$emptyTokens; + $ignore += [ + T_ARRAY => T_ARRAY, + T_CALLABLE => T_CALLABLE, + T_COLON => T_COLON, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_NULL => T_NULL, + T_NULLABLE => T_NULLABLE, + T_PARENT => T_PARENT, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_STRING => T_STRING, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + ]; + + $closer = $this->tokens[$x]['parenthesis_closer']; + for ($arrow = ($closer + 1); $arrow < $numTokens; $arrow++) { + if (isset($ignore[$this->tokens[$arrow]['code']]) === false) { + break; + } + } + + if ($this->tokens[$arrow]['code'] === T_DOUBLE_ARROW) { + $endTokens = [ + T_COLON => true, + T_COMMA => true, + T_SEMICOLON => true, + T_CLOSE_PARENTHESIS => true, + T_CLOSE_SQUARE_BRACKET => true, + T_CLOSE_CURLY_BRACKET => true, + T_CLOSE_SHORT_ARRAY => true, + T_OPEN_TAG => true, + T_CLOSE_TAG => true, + ]; + + $inTernary = false; + $lastEndToken = null; + + for ($scopeCloser = ($arrow + 1); $scopeCloser < $numTokens; $scopeCloser++) { + // Arrow function closer should never be shared with the closer of a match + // control structure. + if (isset($this->tokens[$scopeCloser]['scope_closer'], $this->tokens[$scopeCloser]['scope_condition']) === true + && $scopeCloser === $this->tokens[$scopeCloser]['scope_closer'] + && $this->tokens[$this->tokens[$scopeCloser]['scope_condition']]['code'] === T_MATCH + ) { + if ($arrow < $this->tokens[$scopeCloser]['scope_condition']) { + // Match in return value of arrow function. Move on to the next token. + continue; + } + + // Arrow function as return value for the last match case without trailing comma. + if ($lastEndToken !== null) { + $scopeCloser = $lastEndToken; + break; + } + + for ($lastNonEmpty = ($scopeCloser - 1); $lastNonEmpty > $arrow; $lastNonEmpty--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$lastNonEmpty]['code']]) === false) { + $scopeCloser = $lastNonEmpty; + break 2; + } + } + } + + if (isset($endTokens[$this->tokens[$scopeCloser]['code']]) === true) { + if ($lastEndToken !== null + && ((isset($this->tokens[$scopeCloser]['parenthesis_opener']) === true + && $this->tokens[$scopeCloser]['parenthesis_opener'] < $arrow) + || (isset($this->tokens[$scopeCloser]['bracket_opener']) === true + && $this->tokens[$scopeCloser]['bracket_opener'] < $arrow)) + ) { + for ($lastNonEmpty = ($scopeCloser - 1); $lastNonEmpty > $arrow; $lastNonEmpty--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$lastNonEmpty]['code']]) === false) { + $scopeCloser = $lastNonEmpty; + break; + } + } + } + + break; + } + + if ($inTernary === false + && isset($this->tokens[$scopeCloser]['scope_closer'], $this->tokens[$scopeCloser]['scope_condition']) === true + && $scopeCloser === $this->tokens[$scopeCloser]['scope_closer'] + && $this->tokens[$this->tokens[$scopeCloser]['scope_condition']]['code'] === T_FN + ) { + // Found a nested arrow function that already has the closer set and is in + // the same scope as us, so we can use its closer. + break; + } + + if (isset($this->tokens[$scopeCloser]['scope_closer']) === true + && $this->tokens[$scopeCloser]['code'] !== T_INLINE_ELSE + && $this->tokens[$scopeCloser]['code'] !== T_END_HEREDOC + && $this->tokens[$scopeCloser]['code'] !== T_END_NOWDOC + ) { + // We minus 1 here in case the closer can be shared with us. + $scopeCloser = ($this->tokens[$scopeCloser]['scope_closer'] - 1); + continue; + } + + if (isset($this->tokens[$scopeCloser]['parenthesis_closer']) === true) { + $scopeCloser = $this->tokens[$scopeCloser]['parenthesis_closer']; + $lastEndToken = $scopeCloser; + continue; + } + + if (isset($this->tokens[$scopeCloser]['bracket_closer']) === true) { + $scopeCloser = $this->tokens[$scopeCloser]['bracket_closer']; + $lastEndToken = $scopeCloser; + continue; + } + + if ($this->tokens[$scopeCloser]['code'] === T_INLINE_THEN) { + $inTernary = true; + continue; + } + + if ($this->tokens[$scopeCloser]['code'] === T_INLINE_ELSE) { + if ($inTernary === false) { + break; + } + + $inTernary = false; + continue; + } + }//end for + + if ($scopeCloser !== $numTokens) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t=> token $i on line $line processed as arrow function".PHP_EOL; + echo "\t\t* scope opener set to $arrow *".PHP_EOL; + echo "\t\t* scope closer set to $scopeCloser *".PHP_EOL; + echo "\t\t* parenthesis opener set to $x *".PHP_EOL; + echo "\t\t* parenthesis closer set to $closer *".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_FN; + $this->tokens[$i]['type'] = 'T_FN'; + $this->tokens[$i]['scope_condition'] = $i; + $this->tokens[$i]['scope_opener'] = $arrow; + $this->tokens[$i]['scope_closer'] = $scopeCloser; + $this->tokens[$i]['parenthesis_owner'] = $i; + $this->tokens[$i]['parenthesis_opener'] = $x; + $this->tokens[$i]['parenthesis_closer'] = $closer; + + $this->tokens[$arrow]['code'] = T_FN_ARROW; + $this->tokens[$arrow]['type'] = 'T_FN_ARROW'; + + $this->tokens[$arrow]['scope_condition'] = $i; + $this->tokens[$arrow]['scope_opener'] = $arrow; + $this->tokens[$arrow]['scope_closer'] = $scopeCloser; + $this->tokens[$scopeCloser]['scope_condition'] = $i; + $this->tokens[$scopeCloser]['scope_opener'] = $arrow; + $this->tokens[$scopeCloser]['scope_closer'] = $scopeCloser; + + $opener = $this->tokens[$i]['parenthesis_opener']; + $closer = $this->tokens[$i]['parenthesis_closer']; + $this->tokens[$opener]['parenthesis_owner'] = $i; + $this->tokens[$closer]['parenthesis_owner'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$arrow]['line']; + echo "\t\t* token $arrow on line $line changed from T_DOUBLE_ARROW to T_FN_ARROW".PHP_EOL; + } + }//end if + }//end if + }//end if + + // If after all that, the extra tokens are not set, this is not an arrow function. + if (isset($this->tokens[$i]['scope_closer']) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t=> token $i on line $line is not an arrow function".PHP_EOL; + echo "\t\t* token changed from T_FN to T_STRING".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + } + } else if ($this->tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) { + if (isset($this->tokens[$i]['bracket_closer']) === false) { + continue; + } + + // Unless there is a variable or a bracket before this token, + // it is the start of an array being defined using the short syntax. + $isShortArray = false; + $allowed = [ + T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + T_VARIABLE => T_VARIABLE, + T_OBJECT_OPERATOR => T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR => T_NULLSAFE_OBJECT_OPERATOR, + T_STRING => T_STRING, + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + $allowed += Util\Tokens::$magicConstants; + + for ($x = ($i - 1); $x >= 0; $x--) { + // If we hit a scope opener, the statement has ended + // without finding anything, so it's probably an array + // using PHP 7.1 short list syntax. + if (isset($this->tokens[$x]['scope_opener']) === true) { + $isShortArray = true; + break; + } + + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + if (isset($allowed[$this->tokens[$x]['code']]) === false) { + $isShortArray = true; + } + + break; + } + } + + if ($isShortArray === true) { + $this->tokens[$i]['code'] = T_OPEN_SHORT_ARRAY; + $this->tokens[$i]['type'] = 'T_OPEN_SHORT_ARRAY'; + + $closer = $this->tokens[$i]['bracket_closer']; + $this->tokens[$closer]['code'] = T_CLOSE_SHORT_ARRAY; + $this->tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL; + $line = $this->tokens[$closer]['line']; + echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_MATCH) { + if (isset($this->tokens[$i]['scope_opener'], $this->tokens[$i]['scope_closer']) === false) { + // Not a match expression after all. + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $i changed from T_MATCH to T_STRING".PHP_EOL; + } + + if (isset($this->tokens[$i]['parenthesis_opener'], $this->tokens[$i]['parenthesis_closer']) === true) { + $opener = $this->tokens[$i]['parenthesis_opener']; + $closer = $this->tokens[$i]['parenthesis_closer']; + unset( + $this->tokens[$opener]['parenthesis_owner'], + $this->tokens[$closer]['parenthesis_owner'] + ); + unset( + $this->tokens[$i]['parenthesis_opener'], + $this->tokens[$i]['parenthesis_closer'], + $this->tokens[$i]['parenthesis_owner'] + ); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* cleaned parenthesis of token $i *".PHP_EOL; + } + } + } else { + // Retokenize the double arrows for match expression cases to `T_MATCH_ARROW`. + $searchFor = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + ]; + $searchFor += Util\Tokens::$scopeOpeners; + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($searchFor[$this->tokens[$x]['code']]) === false) { + continue; + } + + if (isset($this->tokens[$x]['scope_closer']) === true) { + $x = $this->tokens[$x]['scope_closer']; + continue; + } + + if (isset($this->tokens[$x]['parenthesis_closer']) === true) { + $x = $this->tokens[$x]['parenthesis_closer']; + continue; + } + + if (isset($this->tokens[$x]['bracket_closer']) === true) { + $x = $this->tokens[$x]['bracket_closer']; + continue; + } + + // This must be a double arrow, but make sure anyhow. + if ($this->tokens[$x]['code'] === T_DOUBLE_ARROW) { + $this->tokens[$x]['code'] = T_MATCH_ARROW; + $this->tokens[$x]['type'] = 'T_MATCH_ARROW'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + } + } + }//end for + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_BITWISE_OR + || $this->tokens[$i]['code'] === T_BITWISE_AND + ) { + /* + Convert "|" to T_TYPE_UNION or leave as T_BITWISE_OR. + Convert "&" to T_TYPE_INTERSECTION or leave as T_BITWISE_AND. + */ + + $allowed = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + T_FALSE => T_FALSE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + ]; + + $suspectedType = null; + $typeTokenCount = 0; + + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + if (isset($allowed[$this->tokens[$x]['code']]) === true) { + ++$typeTokenCount; + continue; + } + + if ($typeTokenCount > 0 + && ($this->tokens[$x]['code'] === T_BITWISE_AND + || $this->tokens[$x]['code'] === T_ELLIPSIS) + ) { + // Skip past reference and variadic indicators for parameter types. + continue; + } + + if ($this->tokens[$x]['code'] === T_VARIABLE) { + // Parameter/Property defaults can not contain variables, so this could be a type. + $suspectedType = 'property or parameter'; + break; + } + + if ($this->tokens[$x]['code'] === T_DOUBLE_ARROW) { + // Possible arrow function. + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_SEMICOLON) { + // Possible abstract method or interface method. + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET + && isset($this->tokens[$x]['scope_condition']) === true + && $this->tokens[$this->tokens[$x]['scope_condition']]['code'] === T_FUNCTION + ) { + $suspectedType = 'return'; + } + + break; + }//end for + + if ($typeTokenCount === 0 || isset($suspectedType) === false) { + // Definitely not a union or intersection type, move on. + continue; + } + + $typeTokenCount = 0; + $typeOperators = [$i]; + $confirmed = false; + + for ($x = ($i - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + if (isset($allowed[$this->tokens[$x]['code']]) === true) { + ++$typeTokenCount; + continue; + } + + // Union and intersection types can't use the nullable operator, but be tolerant to parse errors. + if ($typeTokenCount > 0 && $this->tokens[$x]['code'] === T_NULLABLE) { + continue; + } + + if ($this->tokens[$x]['code'] === T_BITWISE_OR || $this->tokens[$x]['code'] === T_BITWISE_AND) { + $typeOperators[] = $x; + continue; + } + + if ($suspectedType === 'return' && $this->tokens[$x]['code'] === T_COLON) { + $confirmed = true; + break; + } + + if ($suspectedType === 'property or parameter' + && (isset(Util\Tokens::$scopeModifiers[$this->tokens[$x]['code']]) === true + || $this->tokens[$x]['code'] === T_VAR + || $this->tokens[$x]['code'] === T_READONLY) + ) { + // This will also confirm constructor property promotion parameters, but that's fine. + $confirmed = true; + } + + break; + }//end for + + if ($confirmed === false + && $suspectedType === 'property or parameter' + && isset($this->tokens[$i]['nested_parenthesis']) === true + ) { + $parens = $this->tokens[$i]['nested_parenthesis']; + $last = end($parens); + + if (isset($this->tokens[$last]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$last]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $confirmed = true; + } else { + // No parenthesis owner set, this may be an arrow function which has not yet + // had additional processing done. + if (isset($this->tokens[$last]['parenthesis_opener']) === true) { + for ($x = ($this->tokens[$last]['parenthesis_opener'] - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + break; + } + + if ($this->tokens[$x]['code'] === T_FN) { + for (--$x; $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true + || $this->tokens[$x]['code'] === T_BITWISE_AND + ) { + continue; + } + + break; + } + + if ($this->tokens[$x]['code'] !== T_FUNCTION) { + $confirmed = true; + } + } + }//end if + }//end if + + unset($parens, $last); + }//end if + + if ($confirmed === false) { + // Not a union or intersection type after all, move on. + continue; + } + + foreach ($typeOperators as $x) { + if ($this->tokens[$x]['code'] === T_BITWISE_OR) { + $this->tokens[$x]['code'] = T_TYPE_UNION; + $this->tokens[$x]['type'] = 'T_TYPE_UNION'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_BITWISE_OR to T_TYPE_UNION".PHP_EOL; + } + } else { + $this->tokens[$x]['code'] = T_TYPE_INTERSECTION; + $this->tokens[$x]['type'] = 'T_TYPE_INTERSECTION'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_BITWISE_AND to T_TYPE_INTERSECTION".PHP_EOL; + } + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_STATIC) { + for ($x = ($i - 1); $x > 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_INSTANCEOF) { + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_TRUE + || $this->tokens[$i]['code'] === T_FALSE + || $this->tokens[$i]['code'] === T_NULL + ) { + for ($x = ($i + 1); $i < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Non-whitespace content. + break; + } + } + + if (isset($this->tstringContexts[$this->tokens[$x]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + $type = $this->tokens[$i]['type']; + echo "\t* token $i on line $line changed from $type to T_STRING".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + } + }//end if + + if (($this->tokens[$i]['code'] !== T_CASE + && $this->tokens[$i]['code'] !== T_DEFAULT) + || isset($this->tokens[$i]['scope_opener']) === false + ) { + // Only interested in CASE and DEFAULT statements from here on in. + continue; + } + + $scopeOpener = $this->tokens[$i]['scope_opener']; + $scopeCloser = $this->tokens[$i]['scope_closer']; + + // If the first char after the opener is a curly brace + // and that brace has been ignored, it is actually + // opening this case statement and the opener and closer are + // probably set incorrectly. + for ($x = ($scopeOpener + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Non-whitespace content. + break; + } + } + + if ($this->tokens[$x]['code'] === T_CASE || $this->tokens[$x]['code'] === T_DEFAULT) { + // Special case for multiple CASE statements that share the same + // closer. Because we are going backwards through the file, this next + // CASE statement is already fixed, so just use its closer and don't + // worry about fixing anything. + $newCloser = $this->tokens[$x]['scope_closer']; + $this->tokens[$i]['scope_closer'] = $newCloser; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + $line = $this->tokens[$i]['line']; + echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + + continue; + } + + if ($this->tokens[$x]['code'] !== T_OPEN_CURLY_BRACKET + || isset($this->tokens[$x]['scope_condition']) === true + ) { + // Not a CASE/DEFAULT with a curly brace opener. + continue; + } + + // The closer for this CASE/DEFAULT should be the closing curly brace and + // not whatever it already is. The opener needs to be the opening curly + // brace so everything matches up. + $newCloser = $this->tokens[$x]['bracket_closer']; + foreach ([$i, $x, $newCloser] as $index) { + $this->tokens[$index]['scope_condition'] = $i; + $this->tokens[$index]['scope_opener'] = $x; + $this->tokens[$index]['scope_closer'] = $newCloser; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + $tokenType = $this->tokens[$i]['type']; + + $oldType = $this->tokens[$scopeOpener]['type']; + $newType = $this->tokens[$x]['type']; + echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL; + + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + + if ($this->tokens[$scopeOpener]['scope_condition'] === $i) { + unset($this->tokens[$scopeOpener]['scope_condition']); + unset($this->tokens[$scopeOpener]['scope_opener']); + unset($this->tokens[$scopeOpener]['scope_closer']); + } + + if ($this->tokens[$scopeCloser]['scope_condition'] === $i) { + unset($this->tokens[$scopeCloser]['scope_condition']); + unset($this->tokens[$scopeCloser]['scope_opener']); + unset($this->tokens[$scopeCloser]['scope_closer']); + } else { + // We were using a shared closer. All tokens that were + // sharing this closer with us, except for the scope condition + // and it's opener, need to now point to the new closer. + $condition = $this->tokens[$scopeCloser]['scope_condition']; + $start = ($this->tokens[$condition]['scope_opener'] + 1); + for ($y = $start; $y < $scopeCloser; $y++) { + if (isset($this->tokens[$y]['scope_closer']) === true + && $this->tokens[$y]['scope_closer'] === $scopeCloser + ) { + $this->tokens[$y]['scope_closer'] = $newCloser; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$y]['line']; + $tokenType = $this->tokens[$y]['type']; + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + echo "\t\t* token $y ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + } + } + }//end if + + unset($this->tokens[$x]['bracket_opener']); + unset($this->tokens[$x]['bracket_closer']); + unset($this->tokens[$newCloser]['bracket_opener']); + unset($this->tokens[$newCloser]['bracket_closer']); + $this->tokens[$scopeCloser]['conditions'][] = $i; + + // Now fix up all the tokens that think they are + // inside the CASE/DEFAULT statement when they are really outside. + for ($x = $newCloser; $x < $scopeCloser; $x++) { + foreach ($this->tokens[$x]['conditions'] as $num => $oldCond) { + if ($oldCond === $this->tokens[$i]['code']) { + $oldConditions = $this->tokens[$x]['conditions']; + unset($this->tokens[$x]['conditions'][$num]); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Util\Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Util\Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL; + } + + break; + }//end if + }//end foreach + }//end for + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL; + } + + }//end processAdditional() + + + /** + * Takes a token produced from token_get_all() and produces a + * more uniform token. + * + * @param string|array $token The token to convert. + * + * @return array The new token. + */ + public static function standardiseToken($token) + { + if (isset($token[1]) === false) { + if (isset(self::$resolveTokenCache[$token[0]]) === true) { + return self::$resolveTokenCache[$token[0]]; + } + } else { + $cacheKey = null; + if ($token[0] === T_STRING) { + $cacheKey = strtolower($token[1]); + } else if ($token[0] !== T_CURLY_OPEN) { + $cacheKey = $token[0]; + } + + if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) { + $newToken = self::$resolveTokenCache[$cacheKey]; + $newToken['content'] = $token[1]; + return $newToken; + } + } + + if (isset($token[1]) === false) { + return self::resolveSimpleToken($token[0]); + } + + if ($token[0] === T_STRING) { + switch ($cacheKey) { + case 'false': + $newToken['type'] = 'T_FALSE'; + break; + case 'true': + $newToken['type'] = 'T_TRUE'; + break; + case 'null': + $newToken['type'] = 'T_NULL'; + break; + case 'self': + $newToken['type'] = 'T_SELF'; + break; + case 'parent': + $newToken['type'] = 'T_PARENT'; + break; + default: + $newToken['type'] = 'T_STRING'; + break; + } + + $newToken['code'] = constant($newToken['type']); + + self::$resolveTokenCache[$cacheKey] = $newToken; + } else if ($token[0] === T_CURLY_OPEN) { + $newToken = [ + 'code' => T_OPEN_CURLY_BRACKET, + 'type' => 'T_OPEN_CURLY_BRACKET', + ]; + } else { + $newToken = [ + 'code' => $token[0], + 'type' => Util\Tokens::tokenName($token[0]), + ]; + + self::$resolveTokenCache[$token[0]] = $newToken; + }//end if + + $newToken['content'] = $token[1]; + return $newToken; + + }//end standardiseToken() + + + /** + * Converts simple tokens into a format that conforms to complex tokens + * produced by token_get_all(). + * + * Simple tokens are tokens that are not in array form when produced from + * token_get_all(). + * + * @param string $token The simple token to convert. + * + * @return array The new token in array format. + */ + public static function resolveSimpleToken($token) + { + $newToken = []; + + switch ($token) { + case '{': + $newToken['type'] = 'T_OPEN_CURLY_BRACKET'; + break; + case '}': + $newToken['type'] = 'T_CLOSE_CURLY_BRACKET'; + break; + case '[': + $newToken['type'] = 'T_OPEN_SQUARE_BRACKET'; + break; + case ']': + $newToken['type'] = 'T_CLOSE_SQUARE_BRACKET'; + break; + case '(': + $newToken['type'] = 'T_OPEN_PARENTHESIS'; + break; + case ')': + $newToken['type'] = 'T_CLOSE_PARENTHESIS'; + break; + case ':': + $newToken['type'] = 'T_COLON'; + break; + case '.': + $newToken['type'] = 'T_STRING_CONCAT'; + break; + case ';': + $newToken['type'] = 'T_SEMICOLON'; + break; + case '=': + $newToken['type'] = 'T_EQUAL'; + break; + case '*': + $newToken['type'] = 'T_MULTIPLY'; + break; + case '/': + $newToken['type'] = 'T_DIVIDE'; + break; + case '+': + $newToken['type'] = 'T_PLUS'; + break; + case '-': + $newToken['type'] = 'T_MINUS'; + break; + case '%': + $newToken['type'] = 'T_MODULUS'; + break; + case '^': + $newToken['type'] = 'T_BITWISE_XOR'; + break; + case '&': + $newToken['type'] = 'T_BITWISE_AND'; + break; + case '|': + $newToken['type'] = 'T_BITWISE_OR'; + break; + case '~': + $newToken['type'] = 'T_BITWISE_NOT'; + break; + case '<': + $newToken['type'] = 'T_LESS_THAN'; + break; + case '>': + $newToken['type'] = 'T_GREATER_THAN'; + break; + case '!': + $newToken['type'] = 'T_BOOLEAN_NOT'; + break; + case ',': + $newToken['type'] = 'T_COMMA'; + break; + case '@': + $newToken['type'] = 'T_ASPERAND'; + break; + case '$': + $newToken['type'] = 'T_DOLLAR'; + break; + case '`': + $newToken['type'] = 'T_BACKTICK'; + break; + default: + $newToken['type'] = 'T_NONE'; + break; + }//end switch + + $newToken['code'] = constant($newToken['type']); + $newToken['content'] = $token; + + self::$resolveTokenCache[$token] = $newToken; + return $newToken; + + }//end resolveSimpleToken() + + + /** + * Finds a "closer" token (closing parenthesis or square bracket for example) + * Handle parenthesis balancing while searching for closing token + * + * @param array $tokens The list of tokens to iterate searching the closing token (as returned by token_get_all) + * @param int $start The starting position + * @param string|string[] $openerTokens The opening character + * @param string $closerChar The closing character + * + * @return int|null The position of the closing token, if found. NULL otherwise. + */ + private function findCloser(array &$tokens, $start, $openerTokens, $closerChar) + { + $numTokens = count($tokens); + $stack = [0]; + $closer = null; + $openerTokens = (array) $openerTokens; + + for ($x = $start; $x < $numTokens; $x++) { + if (in_array($tokens[$x], $openerTokens, true) === true + || (is_array($tokens[$x]) === true && in_array($tokens[$x][1], $openerTokens, true) === true) + ) { + $stack[] = $x; + } else if ($tokens[$x] === $closerChar) { + array_pop($stack); + if (empty($stack) === true) { + $closer = $x; + break; + } + } + } + + return $closer; + + }//end findCloser() + + + /** + * PHP 8 attributes parser for PHP < 8 + * Handles single-line and multiline attributes. + * + * @param array $tokens The original array of tokens (as returned by token_get_all) + * @param int $stackPtr The current position in token array + * + * @return array|null The array of parsed attribute tokens + */ + private function parsePhpAttribute(array &$tokens, $stackPtr) + { + + $token = $tokens[$stackPtr]; + + $commentBody = substr($token[1], 2); + $subTokens = @token_get_all(' $subToken) { + if (is_array($subToken) === true + && $subToken[0] === T_COMMENT + && strpos($subToken[1], '#[') === 0 + ) { + $reparsed = $this->parsePhpAttribute($subTokens, $i); + if ($reparsed !== null) { + array_splice($subTokens, $i, 1, $reparsed); + } else { + $subToken[0] = T_ATTRIBUTE; + } + } + } + + array_splice($subTokens, 0, 1, [[T_ATTRIBUTE, '#[']]); + + // Go looking for the close bracket. + $bracketCloser = $this->findCloser($subTokens, 1, '[', ']'); + if (PHP_VERSION_ID < 80000 && $bracketCloser === null) { + foreach (array_slice($tokens, ($stackPtr + 1)) as $token) { + if (is_array($token) === true) { + $commentBody .= $token[1]; + } else { + $commentBody .= $token; + } + } + + $subTokens = @token_get_all('findCloser($subTokens, 1, '[', ']'); + if ($bracketCloser !== null) { + array_splice($tokens, ($stackPtr + 1), count($tokens), array_slice($subTokens, ($bracketCloser + 1))); + $subTokens = array_slice($subTokens, 0, ($bracketCloser + 1)); + } + } + + if ($bracketCloser === null) { + return null; + } + + return $subTokens; + + }//end parsePhpAttribute() + + + /** + * Creates a map for the attributes tokens that surround other tokens. + * + * @return void + */ + private function createAttributesNestingMap() + { + $map = []; + for ($i = 0; $i < $this->numTokens; $i++) { + if (isset($this->tokens[$i]['attribute_opener']) === true + && $i === $this->tokens[$i]['attribute_opener'] + ) { + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + + if (isset($this->tokens[$i]['attribute_closer']) === true) { + $map[$this->tokens[$i]['attribute_opener']] + = $this->tokens[$i]['attribute_closer']; + } + } else if (isset($this->tokens[$i]['attribute_closer']) === true + && $i === $this->tokens[$i]['attribute_closer'] + ) { + array_pop($map); + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + } else { + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + }//end if + }//end for + + }//end createAttributesNestingMap() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php new file mode 100644 index 000000000..c79323ccd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php @@ -0,0 +1,1732 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +abstract class Tokenizer +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + protected $config = null; + + /** + * The EOL char used in the content. + * + * @var string + */ + protected $eolChar = []; + + /** + * A token-based representation of the content. + * + * @var array + */ + protected $tokens = []; + + /** + * The number of tokens in the tokens array. + * + * @var integer + */ + protected $numTokens = 0; + + /** + * A list of tokens that are allowed to open a scope. + * + * @var array + */ + public $scopeOpeners = []; + + /** + * A list of tokens that end the scope. + * + * @var array + */ + public $endScopeTokens = []; + + /** + * Known lengths of tokens. + * + * @var array + */ + public $knownLengths = []; + + /** + * A list of lines being ignored due to error suppression comments. + * + * @var array + */ + public $ignoredLines = []; + + + /** + * Initialise and run the tokenizer. + * + * @param string $content The content to tokenize, + * @param \PHP_CodeSniffer\Config | null $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, $config, $eolChar='\n') + { + $this->eolChar = $eolChar; + + $this->config = $config; + $this->tokens = $this->tokenize($content); + + if ($config === null) { + return; + } + + $this->createPositionMap(); + $this->createTokenMap(); + $this->createParenthesisNestingMap(); + $this->createScopeMap(); + $this->createLevelMap(); + + // Allow the tokenizer to do additional processing if required. + $this->processAdditional(); + + }//end __construct() + + + /** + * Checks the content to see if it looks minified. + * + * @param string $content The content to tokenize. + * @param string $eolChar The EOL char used in the content. + * + * @return boolean + */ + protected function isMinifiedContent($content, $eolChar='\n') + { + // Minified files often have a very large number of characters per line + // and cause issues when tokenizing. + $numChars = strlen($content); + $numLines = (substr_count($content, $eolChar) + 1); + $average = ($numChars / $numLines); + if ($average > 100) { + return true; + } + + return false; + + }//end isMinifiedContent() + + + /** + * Gets the array of tokens. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + + }//end getTokens() + + + /** + * Creates an array of tokens when given some content. + * + * @param string $string The string to tokenize. + * + * @return array + */ + abstract protected function tokenize($string); + + + /** + * Performs additional processing after main tokenizing. + * + * @return void + */ + abstract protected function processAdditional(); + + + /** + * Sets token position information. + * + * Can also convert tabs into spaces. Each tab can represent between + * 1 and $width spaces, so this cannot be a straight string replace. + * + * @return void + */ + private function createPositionMap() + { + $currColumn = 1; + $lineNumber = 1; + $eolLen = strlen($this->eolChar); + $ignoring = null; + $inTests = defined('PHP_CODESNIFFER_IN_TESTS'); + + $checkEncoding = false; + if (function_exists('iconv_strlen') === true) { + $checkEncoding = true; + } + + $checkAnnotations = $this->config->annotations; + $encoding = $this->config->encoding; + $tabWidth = $this->config->tabWidth; + + $tokensWithTabs = [ + T_WHITESPACE => true, + T_COMMENT => true, + T_DOC_COMMENT => true, + T_DOC_COMMENT_WHITESPACE => true, + T_DOC_COMMENT_STRING => true, + T_CONSTANT_ENCAPSED_STRING => true, + T_DOUBLE_QUOTED_STRING => true, + T_HEREDOC => true, + T_NOWDOC => true, + T_INLINE_HTML => true, + ]; + + $this->numTokens = count($this->tokens); + for ($i = 0; $i < $this->numTokens; $i++) { + $this->tokens[$i]['line'] = $lineNumber; + $this->tokens[$i]['column'] = $currColumn; + + if (isset($this->knownLengths[$this->tokens[$i]['code']]) === true) { + // There are no tabs in the tokens we know the length of. + $length = $this->knownLengths[$this->tokens[$i]['code']]; + $currColumn += $length; + } else if ($tabWidth === 0 + || isset($tokensWithTabs[$this->tokens[$i]['code']]) === false + || strpos($this->tokens[$i]['content'], "\t") === false + ) { + // There are no tabs in this content, or we aren't replacing them. + if ($checkEncoding === true) { + // Not using the default encoding, so take a bit more care. + $oldLevel = error_reporting(); + error_reporting(0); + $length = iconv_strlen($this->tokens[$i]['content'], $encoding); + error_reporting($oldLevel); + + if ($length === false) { + // String contained invalid characters, so revert to default. + $length = strlen($this->tokens[$i]['content']); + } + } else { + $length = strlen($this->tokens[$i]['content']); + } + + $currColumn += $length; + } else { + $this->replaceTabsInToken($this->tokens[$i]); + $length = $this->tokens[$i]['length']; + $currColumn += $length; + }//end if + + $this->tokens[$i]['length'] = $length; + + if (isset($this->knownLengths[$this->tokens[$i]['code']]) === false + && strpos($this->tokens[$i]['content'], $this->eolChar) !== false + ) { + $lineNumber++; + $currColumn = 1; + + // Newline chars are not counted in the token length. + $this->tokens[$i]['length'] -= $eolLen; + } + + if ($this->tokens[$i]['code'] === T_COMMENT + || $this->tokens[$i]['code'] === T_DOC_COMMENT_STRING + || $this->tokens[$i]['code'] === T_DOC_COMMENT_TAG + || ($inTests === true && $this->tokens[$i]['code'] === T_INLINE_HTML) + ) { + $commentText = ltrim($this->tokens[$i]['content'], " \t/*#"); + $commentText = rtrim($commentText, " */\t\r\n"); + $commentTextLower = strtolower($commentText); + if (strpos($commentText, '@codingStandards') !== false) { + // If this comment is the only thing on the line, it tells us + // to ignore the following line. If the line contains other content + // then we are just ignoring this one single line. + $ownLine = false; + if ($i > 0) { + for ($prev = ($i - 1); $prev >= 0; $prev--) { + if ($this->tokens[$prev]['code'] === T_WHITESPACE) { + continue; + } + + break; + } + + if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) { + $ownLine = true; + } + } + + if ($ignoring === null + && strpos($commentText, '@codingStandardsIgnoreStart') !== false + ) { + $ignoring = ['.all' => true]; + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + } else if ($ignoring !== null + && strpos($commentText, '@codingStandardsIgnoreEnd') !== false + ) { + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } else { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $ignoring = null; + } else if ($ignoring === null + && strpos($commentText, '@codingStandardsIgnoreLine') !== false + ) { + $ignoring = ['.all' => true]; + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoring; + } else { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $ignoring = null; + }//end if + } else if (substr($commentTextLower, 0, 6) === 'phpcs:' + || substr($commentTextLower, 0, 7) === '@phpcs:' + ) { + // If the @phpcs: syntax is being used, strip the @ to make + // comparisons easier. + if ($commentText[0] === '@') { + $commentText = substr($commentText, 1); + $commentTextLower = strtolower($commentText); + } + + // If there is a comment on the end, strip it off. + $commentStart = strpos($commentTextLower, ' --'); + if ($commentStart !== false) { + $commentText = substr($commentText, 0, $commentStart); + $commentTextLower = strtolower($commentText); + } + + // If this comment is the only thing on the line, it tells us + // to ignore the following line. If the line contains other content + // then we are just ignoring this one single line. + $lineHasOtherContent = false; + $lineHasOtherTokens = false; + if ($i > 0) { + for ($prev = ($i - 1); $prev > 0; $prev--) { + if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) { + // Changed lines. + break; + } + + if ($this->tokens[$prev]['code'] === T_WHITESPACE + || $this->tokens[$prev]['code'] === T_DOC_COMMENT_WHITESPACE + || ($this->tokens[$prev]['code'] === T_INLINE_HTML + && trim($this->tokens[$prev]['content']) === '') + ) { + continue; + } + + $lineHasOtherTokens = true; + + if ($this->tokens[$prev]['code'] === T_OPEN_TAG + || $this->tokens[$prev]['code'] === T_DOC_COMMENT_STAR + ) { + continue; + } + + $lineHasOtherContent = true; + break; + }//end for + + $changedLines = false; + for ($next = $i; $next < $this->numTokens; $next++) { + if ($changedLines === true) { + // Changed lines. + break; + } + + if (isset($this->knownLengths[$this->tokens[$next]['code']]) === false + && strpos($this->tokens[$next]['content'], $this->eolChar) !== false + ) { + // Last token on the current line. + $changedLines = true; + } + + if ($next === $i) { + continue; + } + + if ($this->tokens[$next]['code'] === T_WHITESPACE + || $this->tokens[$next]['code'] === T_DOC_COMMENT_WHITESPACE + || ($this->tokens[$next]['code'] === T_INLINE_HTML + && trim($this->tokens[$next]['content']) === '') + ) { + continue; + } + + $lineHasOtherTokens = true; + + if ($this->tokens[$next]['code'] === T_CLOSE_TAG) { + continue; + } + + $lineHasOtherContent = true; + break; + }//end for + }//end if + + if (substr($commentTextLower, 0, 9) === 'phpcs:set') { + // Ignore standards for complete lines that change sniff settings. + if ($lineHasOtherTokens === false) { + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } + + // Need to maintain case here, to get the correct sniff code. + $parts = explode(' ', substr($commentText, 10)); + if (count($parts) >= 2) { + $sniffParts = explode('.', $parts[0]); + if (count($sniffParts) >= 3) { + $this->tokens[$i]['sniffCode'] = array_shift($parts); + $this->tokens[$i]['sniffProperty'] = array_shift($parts); + $this->tokens[$i]['sniffPropertyValue'] = rtrim(implode(' ', $parts), " */\r\n"); + } + } + + $this->tokens[$i]['code'] = T_PHPCS_SET; + $this->tokens[$i]['type'] = 'T_PHPCS_SET'; + } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile') { + // The whole file will be ignored, but at least set the correct token. + $this->tokens[$i]['code'] = T_PHPCS_IGNORE_FILE; + $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE_FILE'; + } else if (substr($commentTextLower, 0, 13) === 'phpcs:disable') { + if ($lineHasOtherContent === false) { + // Completely ignore the comment line. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } + + if ($ignoring === null) { + $ignoring = []; + } + + $disabledSniffs = []; + + $additionalText = substr($commentText, 14); + if (empty($additionalText) === true) { + $ignoring = ['.all' => true]; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $sniffCode = trim($sniffCode); + $disabledSniffs[$sniffCode] = true; + $ignoring[$sniffCode] = true; + + // This newly disabled sniff might be disabling an existing + // enabled exception that we are tracking. + if (isset($ignoring['.except']) === true) { + foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring['.except'][$ignoredSniffCode]); + } + } + + if (empty($ignoring['.except']) === true) { + unset($ignoring['.except']); + } + } + }//end foreach + }//end if + + $this->tokens[$i]['code'] = T_PHPCS_DISABLE; + $this->tokens[$i]['type'] = 'T_PHPCS_DISABLE'; + $this->tokens[$i]['sniffCodes'] = $disabledSniffs; + } else if (substr($commentTextLower, 0, 12) === 'phpcs:enable') { + if ($ignoring !== null) { + $enabledSniffs = []; + + $additionalText = substr($commentText, 13); + if (empty($additionalText) === true) { + $ignoring = null; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $sniffCode = trim($sniffCode); + $enabledSniffs[$sniffCode] = true; + + // This new enabled sniff might remove previously disabled + // sniffs if it is actually a standard or category of sniffs. + foreach (array_keys($ignoring) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring[$ignoredSniffCode]); + } + } + + // This new enabled sniff might be able to clear up + // previously enabled sniffs if it is actually a standard or + // category of sniffs. + if (isset($ignoring['.except']) === true) { + foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring['.except'][$ignoredSniffCode]); + } + } + } + }//end foreach + + if (empty($ignoring) === true) { + $ignoring = null; + } else { + if (isset($ignoring['.except']) === true) { + $ignoring['.except'] += $enabledSniffs; + } else { + $ignoring['.except'] = $enabledSniffs; + } + } + }//end if + + if ($lineHasOtherContent === false) { + // Completely ignore the comment line. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } else { + // The comment is on the same line as the code it is ignoring, + // so respect the new ignore rules. + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $this->tokens[$i]['sniffCodes'] = $enabledSniffs; + }//end if + + $this->tokens[$i]['code'] = T_PHPCS_ENABLE; + $this->tokens[$i]['type'] = 'T_PHPCS_ENABLE'; + } else if (substr($commentTextLower, 0, 12) === 'phpcs:ignore') { + $ignoreRules = []; + + $additionalText = substr($commentText, 13); + if (empty($additionalText) === true) { + $ignoreRules = ['.all' => true]; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $ignoreRules[trim($sniffCode)] = true; + } + } + + $this->tokens[$i]['code'] = T_PHPCS_IGNORE; + $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE'; + $this->tokens[$i]['sniffCodes'] = $ignoreRules; + + if ($ignoring !== null) { + $ignoreRules += $ignoring; + } + + if ($lineHasOtherContent === false) { + // Completely ignore the comment line, and set the following + // line to include the ignore rules we've set. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoreRules; + } else { + // The comment is on the same line as the code it is ignoring, + // so respect the ignore rules it set. + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoreRules; + } + }//end if + }//end if + }//end if + + if ($ignoring !== null && isset($this->ignoredLines[$this->tokens[$i]['line']]) === false) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + }//end for + + // If annotations are being ignored, we clear out all the ignore rules + // but leave the annotations tokenized as normal. + if ($checkAnnotations === false) { + $this->ignoredLines = []; + } + + }//end createPositionMap() + + + /** + * Replaces tabs in original token content with spaces. + * + * Each tab can represent between 1 and $config->tabWidth spaces, + * so this cannot be a straight string replace. The original content + * is placed into an orig_content index and the new token length is also + * set in the length index. + * + * @param array $token The token to replace tabs inside. + * @param string $prefix The character to use to represent the start of a tab. + * @param string $padding The character to use to represent the end of a tab. + * @param int $tabWidth The number of spaces each tab represents. + * + * @return void + */ + public function replaceTabsInToken(&$token, $prefix=' ', $padding=' ', $tabWidth=null) + { + $checkEncoding = false; + if (function_exists('iconv_strlen') === true) { + $checkEncoding = true; + } + + $currColumn = $token['column']; + if ($tabWidth === null) { + $tabWidth = $this->config->tabWidth; + if ($tabWidth === 0) { + $tabWidth = 1; + } + } + + if (rtrim($token['content'], "\t") === '') { + // String only contains tabs, so we can shortcut the process. + $numTabs = strlen($token['content']); + + $firstTabSize = ($tabWidth - (($currColumn - 1) % $tabWidth)); + $length = ($firstTabSize + ($tabWidth * ($numTabs - 1))); + $newContent = $prefix.str_repeat($padding, ($length - 1)); + } else { + // We need to determine the length of each tab. + $tabs = explode("\t", $token['content']); + + $numTabs = (count($tabs) - 1); + $tabNum = 0; + $newContent = ''; + $length = 0; + + foreach ($tabs as $content) { + if ($content !== '') { + $newContent .= $content; + if ($checkEncoding === true) { + // Not using the default encoding, so take a bit more care. + $oldLevel = error_reporting(); + error_reporting(0); + $contentLength = iconv_strlen($content, $this->config->encoding); + error_reporting($oldLevel); + if ($contentLength === false) { + // String contained invalid characters, so revert to default. + $contentLength = strlen($content); + } + } else { + $contentLength = strlen($content); + } + + $currColumn += $contentLength; + $length += $contentLength; + } + + // The last piece of content does not have a tab after it. + if ($tabNum === $numTabs) { + break; + } + + // Process the tab that comes after the content. + $tabNum++; + + // Move the pointer to the next tab stop. + $pad = ($tabWidth - ($currColumn + $tabWidth - 1) % $tabWidth); + $currColumn += $pad; + $length += $pad; + $newContent .= $prefix.str_repeat($padding, ($pad - 1)); + }//end foreach + }//end if + + $token['orig_content'] = $token['content']; + $token['content'] = $newContent; + $token['length'] = $length; + + }//end replaceTabsInToken() + + + /** + * Creates a map of brackets positions. + * + * @return void + */ + private function createTokenMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START TOKEN MAP ***".PHP_EOL; + } + + $squareOpeners = []; + $curlyOpeners = []; + $this->numTokens = count($this->tokens); + + $openers = []; + $openOwner = null; + + for ($i = 0; $i < $this->numTokens; $i++) { + /* + Parenthesis mapping. + */ + + if (isset(Util\Tokens::$parenthesisOpeners[$this->tokens[$i]['code']]) === true) { + $this->tokens[$i]['parenthesis_opener'] = null; + $this->tokens[$i]['parenthesis_closer'] = null; + $this->tokens[$i]['parenthesis_owner'] = $i; + $openOwner = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found parenthesis owner at $i".PHP_EOL; + } + } else if ($this->tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $openers[] = $i; + $this->tokens[$i]['parenthesis_opener'] = $i; + if ($openOwner !== null) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found parenthesis opener at $i for $openOwner".PHP_EOL; + } + + $this->tokens[$openOwner]['parenthesis_opener'] = $i; + $this->tokens[$i]['parenthesis_owner'] = $openOwner; + $openOwner = null; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found unowned parenthesis opener at $i".PHP_EOL; + } + } else if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + // Did we set an owner for this set of parenthesis? + $numOpeners = count($openers); + if ($numOpeners !== 0) { + $opener = array_pop($openers); + if (isset($this->tokens[$opener]['parenthesis_owner']) === true) { + $owner = $this->tokens[$opener]['parenthesis_owner']; + + $this->tokens[$owner]['parenthesis_closer'] = $i; + $this->tokens[$i]['parenthesis_owner'] = $owner; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found parenthesis closer at $i for $owner".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found unowned parenthesis closer at $i for $opener".PHP_EOL; + } + + $this->tokens[$i]['parenthesis_opener'] = $opener; + $this->tokens[$i]['parenthesis_closer'] = $i; + $this->tokens[$opener]['parenthesis_closer'] = $i; + }//end if + } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE) { + $openers[] = $i; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found attribute opener at $i".PHP_EOL; + } + + $this->tokens[$i]['attribute_opener'] = $i; + $this->tokens[$i]['attribute_closer'] = null; + } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE_END) { + $numOpeners = count($openers); + if ($numOpeners !== 0) { + $opener = array_pop($openers); + if (isset($this->tokens[$opener]['attribute_opener']) === true) { + $this->tokens[$opener]['attribute_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found attribute closer at $i for $opener".PHP_EOL; + } + + for ($x = ($opener + 1); $x <= $i; ++$x) { + if (isset($this->tokens[$x]['attribute_closer']) === true) { + continue; + } + + $this->tokens[$x]['attribute_opener'] = $opener; + $this->tokens[$x]['attribute_closer'] = $i; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found unowned attribute closer at $i for $opener".PHP_EOL; + } + }//end if + }//end if + + /* + Bracket mapping. + */ + + switch ($this->tokens[$i]['code']) { + case T_OPEN_SQUARE_BRACKET: + $squareOpeners[] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "=> Found square bracket opener at $i".PHP_EOL; + } + break; + case T_OPEN_CURLY_BRACKET: + if (isset($this->tokens[$i]['scope_closer']) === false) { + $curlyOpeners[] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "=> Found curly bracket opener at $i".PHP_EOL; + } + } + break; + case T_CLOSE_SQUARE_BRACKET: + if (empty($squareOpeners) === false) { + $opener = array_pop($squareOpeners); + $this->tokens[$i]['bracket_opener'] = $opener; + $this->tokens[$i]['bracket_closer'] = $i; + $this->tokens[$opener]['bracket_opener'] = $opener; + $this->tokens[$opener]['bracket_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "\t=> Found square bracket closer at $i for $opener".PHP_EOL; + } + } + break; + case T_CLOSE_CURLY_BRACKET: + if (empty($curlyOpeners) === false + && isset($this->tokens[$i]['scope_opener']) === false + ) { + $opener = array_pop($curlyOpeners); + $this->tokens[$i]['bracket_opener'] = $opener; + $this->tokens[$i]['bracket_closer'] = $i; + $this->tokens[$opener]['bracket_opener'] = $opener; + $this->tokens[$opener]['bracket_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "\t=> Found curly bracket closer at $i for $opener".PHP_EOL; + } + } + break; + default: + continue 2; + }//end switch + }//end for + + // Cleanup for any openers that we didn't find closers for. + // This typically means there was a syntax error breaking things. + foreach ($openers as $opener) { + unset($this->tokens[$opener]['parenthesis_opener']); + unset($this->tokens[$opener]['parenthesis_owner']); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END TOKEN MAP ***".PHP_EOL; + } + + }//end createTokenMap() + + + /** + * Creates a map for the parenthesis tokens that surround other tokens. + * + * @return void + */ + private function createParenthesisNestingMap() + { + $map = []; + for ($i = 0; $i < $this->numTokens; $i++) { + if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_opener'] + ) { + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + + if (isset($this->tokens[$i]['parenthesis_closer']) === true) { + $map[$this->tokens[$i]['parenthesis_opener']] + = $this->tokens[$i]['parenthesis_closer']; + } + } else if (isset($this->tokens[$i]['parenthesis_closer']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + array_pop($map); + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + } else { + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + }//end if + }//end for + + }//end createParenthesisNestingMap() + + + /** + * Creates a scope map of tokens that open scopes. + * + * @return void + * @see recurseScopeMap() + */ + private function createScopeMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START SCOPE MAP ***".PHP_EOL; + } + + for ($i = 0; $i < $this->numTokens; $i++) { + // Check to see if the current token starts a new scope. + if (isset($this->scopeOpeners[$this->tokens[$i]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + echo "\tStart scope map at $i:$type => $content".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_condition']) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* already processed, skipping *".PHP_EOL; + } + + continue; + } + + $i = $this->recurseScopeMap($i); + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END SCOPE MAP ***".PHP_EOL; + } + + }//end createScopeMap() + + + /** + * Recurses though the scope openers to build a scope map. + * + * @param int $stackPtr The position in the stack of the token that + * opened the scope (eg. an IF token or FOR token). + * @param int $depth How many scope levels down we are. + * @param int $ignore How many curly braces we are ignoring. + * + * @return int The position in the stack that closed the scope. + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the nesting level gets too deep. + */ + private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "=> Begin scope map recursion at token $stackPtr with depth $depth".PHP_EOL; + } + + $opener = null; + $currType = $this->tokens[$stackPtr]['code']; + $startLine = $this->tokens[$stackPtr]['line']; + + // We will need this to restore the value if we end up + // returning a token ID that causes our calling function to go back + // over already ignored braces. + $originalIgnore = $ignore; + + // If the start token for this scope opener is the same as + // the scope token, we have already found our opener. + if (isset($this->scopeOpeners[$currType]['start'][$currType]) === true) { + $opener = $stackPtr; + } + + for ($i = ($stackPtr + 1); $i < $this->numTokens; $i++) { + $tokenType = $this->tokens[$i]['code']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $line = $this->tokens[$i]['line']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", $depth); + echo "Process token $i on line $line ["; + if ($opener !== null) { + echo "opener:$opener;"; + } + + if ($ignore > 0) { + echo "ignore=$ignore;"; + } + + echo "]: $type => $content".PHP_EOL; + }//end if + + // Very special case for IF statements in PHP that can be defined without + // scope tokens. E.g., if (1) 1; 1 ? (1 ? 1 : 1) : 1; + // If an IF statement below this one has an opener but no + // keyword, the opener will be incorrectly assigned to this IF statement. + // The same case also applies to USE statements, which don't have to have + // openers, so a following USE statement can cause an incorrect brace match. + if (($currType === T_IF || $currType === T_ELSE || $currType === T_USE) + && $opener === null + && ($this->tokens[$i]['code'] === T_SEMICOLON + || $this->tokens[$i]['code'] === T_CLOSE_TAG) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + if ($this->tokens[$i]['code'] === T_SEMICOLON) { + $closerType = 'semicolon'; + } else { + $closerType = 'close tag'; + } + + echo "=> Found $closerType before scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return $i; + } + + // Special case for PHP control structures that have no braces. + // If we find a curly brace closer before we find the opener, + // we're not going to find an opener. That closer probably belongs to + // a control structure higher up. + if ($opener === null + && $ignore === 0 + && $tokenType === T_CLOSE_CURLY_BRACKET + && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found curly brace closer before scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return ($i - 1); + } + + if ($opener !== null + && (isset($this->tokens[$i]['scope_opener']) === false + || $this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) + && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true + ) { + if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) { + // The last opening bracket must have been for a string + // offset or alike, so let's ignore it. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + continue; + } else if ($this->tokens[$opener]['code'] === T_OPEN_CURLY_BRACKET + && $tokenType !== T_CLOSE_CURLY_BRACKET + ) { + // The opener is a curly bracket so the closer must be a curly bracket as well. + // We ignore this closer to handle cases such as T_ELSE or T_ELSEIF being considered + // a closer of T_IF when it should not. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Ignoring non-curly scope closer for $stackPtr:$type".PHP_EOL; + } + } else { + $scopeCloser = $i; + $todo = [ + $stackPtr, + $opener, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + $closerType = $this->tokens[$scopeCloser]['type']; + echo str_repeat("\t", $depth); + echo "=> Found scope closer ($scopeCloser:$closerType) for $stackPtr:$type".PHP_EOL; + } + + $validCloser = true; + if (($this->tokens[$stackPtr]['code'] === T_IF || $this->tokens[$stackPtr]['code'] === T_ELSEIF) + && ($tokenType === T_ELSE || $tokenType === T_ELSEIF) + ) { + // To be a closer, this token must have an opener. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer needs to be tested *".PHP_EOL; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + + if (isset($this->tokens[$scopeCloser]['scope_opener']) === false) { + $validCloser = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer is not valid (no opener found) *".PHP_EOL; + } + } else if ($this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['code'] !== $this->tokens[$opener]['code']) { + $validCloser = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + $type = $this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['type']; + $openerType = $this->tokens[$opener]['type']; + echo "* closer is not valid (mismatched opener type; $type != $openerType) *".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer was valid *".PHP_EOL; + } + } else { + // The closer was not processed, so we need to + // complete that token as well. + $todo[] = $scopeCloser; + }//end if + + if ($validCloser === true) { + foreach ($todo as $token) { + $this->tokens[$token]['scope_condition'] = $stackPtr; + $this->tokens[$token]['scope_opener'] = $opener; + $this->tokens[$token]['scope_closer'] = $scopeCloser; + } + + if ($this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) { + // As we are going back to where we started originally, restore + // the ignore value back to its original value. + $ignore = $originalIgnore; + return $opener; + } else if ($scopeCloser === $i + && isset($this->scopeOpeners[$tokenType]) === true + ) { + // Unset scope_condition here or else the token will appear to have + // already been processed, and it will be skipped. Normally we want that, + // but in this case, the token is both a closer and an opener, so + // it needs to act like an opener. This is also why we return the + // token before this one; so the closer has a chance to be processed + // a second time, but as an opener. + unset($this->tokens[$scopeCloser]['scope_condition']); + return ($i - 1); + } else { + return $i; + } + } else { + continue; + }//end if + }//end if + }//end if + + // Is this an opening condition ? + if (isset($this->scopeOpeners[$tokenType]) === true) { + if ($opener === null) { + if ($tokenType === T_USE) { + // PHP use keywords are special because they can be + // used as blocks but also inline in function definitions. + // So if we find them nested inside another opener, just skip them. + continue; + } + + if ($tokenType === T_NAMESPACE) { + // PHP namespace keywords are special because they can be + // used as blocks but also inline as operators. + // So if we find them nested inside another opener, just skip them. + continue; + } + + if ($tokenType === T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_FUNCTION + ) { + // Probably a closure, so process it manually. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found function before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_closer']) === true) { + // We've already processed this closure. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + $i = $this->tokens[$i]['scope_closer']; + continue; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + continue; + }//end if + + if ($tokenType === T_CLASS) { + // Probably an anonymous class inside another anonymous class, + // so process it manually. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found class before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_closer']) === true) { + // We've already processed this anon class. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + $i = $this->tokens[$i]['scope_closer']; + continue; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + continue; + }//end if + + // Found another opening condition but still haven't + // found our opener, so we are never going to find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found new opening condition before scope opener for $stackPtr:$type, "; + } + + if (($this->tokens[$stackPtr]['code'] === T_IF + || $this->tokens[$stackPtr]['code'] === T_ELSEIF + || $this->tokens[$stackPtr]['code'] === T_ELSE) + && ($this->tokens[$i]['code'] === T_ELSE + || $this->tokens[$i]['code'] === T_ELSEIF) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "continuing".PHP_EOL; + } + + return ($i - 1); + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "backtracking".PHP_EOL; + } + + return $stackPtr; + } + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* token is an opening condition *'.PHP_EOL; + } + + $isShared = ($this->scopeOpeners[$tokenType]['shared'] === true); + + if (isset($this->tokens[$i]['scope_condition']) === true) { + // We've been here before. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + if ($isShared === false + && isset($this->tokens[$i]['scope_closer']) === true + ) { + $i = $this->tokens[$i]['scope_closer']; + } + + continue; + } else if ($currType === $tokenType + && $isShared === false + && $opener === null + ) { + // We haven't yet found our opener, but we have found another + // scope opener which is the same type as us, and we don't + // share openers, so we will never find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* it was another token\'s opener, bailing *'.PHP_EOL; + } + + return $stackPtr; + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* searching for opener *'.PHP_EOL; + } + + if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { + $oldIgnore = $ignore; + $ignore = 0; + } + + // PHP has a max nesting level for functions. Stop before we hit that limit + // because too many loops means we've run into trouble anyway. + if ($depth > 50) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* reached maximum nesting level; aborting *'.PHP_EOL; + } + + throw new TokenizerException('Maximum nesting level reached; file could not be processed'); + } + + $oldDepth = $depth; + if ($isShared === true + && isset($this->scopeOpeners[$tokenType]['with'][$currType]) === true + ) { + // Don't allow the depth to increment because this is + // possibly not a true nesting if we are sharing our closer. + // This can happen, for example, when a SWITCH has a large + // number of CASE statements with the same shared BREAK. + $depth--; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + $depth = $oldDepth; + + if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { + $ignore = $oldIgnore; + } + }//end if + }//end if + + if (isset($this->scopeOpeners[$currType]['start'][$tokenType]) === true + && $opener === null + ) { + if ($tokenType === T_OPEN_CURLY_BRACKET) { + if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true + && $i < $this->tokens[$stackPtr]['parenthesis_closer'] + ) { + // We found a curly brace inside the condition of the + // current scope opener, so it must be a string offset. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace inside condition *'.PHP_EOL; + } + + $ignore++; + } else { + // Make sure this is actually an opener and not a + // string offset (e.g., $var{0}). + for ($x = ($i - 1); $x > 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } else { + // If the first non-whitespace/comment token looks like this + // brace is a string offset, or this brace is mid-way through + // a new statement, it isn't a scope opener. + $disallowed = Util\Tokens::$assignmentTokens; + $disallowed += [ + T_DOLLAR => true, + T_VARIABLE => true, + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_COMMA => true, + T_OPEN_PARENTHESIS => true, + ]; + + if (isset($disallowed[$this->tokens[$x]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace *'.PHP_EOL; + } + + $ignore++; + } + + break; + }//end if + }//end for + }//end if + }//end if + + if ($ignore === 0 || $tokenType !== T_OPEN_CURLY_BRACKET) { + $openerNested = isset($this->tokens[$i]['nested_parenthesis']); + $ownerNested = isset($this->tokens[$stackPtr]['nested_parenthesis']); + + if (($openerNested === true && $ownerNested === false) + || ($openerNested === false && $ownerNested === true) + || ($openerNested === true + && $this->tokens[$i]['nested_parenthesis'] !== $this->tokens[$stackPtr]['nested_parenthesis']) + ) { + // We found the a token that looks like the opener, but it's nested differently. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + echo str_repeat("\t", $depth); + echo "* ignoring possible opener $i:$type as nested parenthesis don't match *".PHP_EOL; + } + } else { + // We found the opening scope token for $currType. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + } + + $opener = $i; + } + }//end if + } else if ($tokenType === T_SEMICOLON + && $opener === null + && (isset($this->tokens[$stackPtr]['parenthesis_closer']) === false + || $i > $this->tokens[$stackPtr]['parenthesis_closer']) + ) { + // Found the end of a statement but still haven't + // found our opener, so we are never going to find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found end of statement before scope opener for $stackPtr:$type, continuing".PHP_EOL; + } + + return ($i - 1); + } else if ($tokenType === T_OPEN_PARENTHESIS) { + if (isset($this->tokens[$i]['parenthesis_owner']) === true) { + $owner = $this->tokens[$i]['parenthesis_owner']; + if (isset(Util\Tokens::$scopeOpeners[$this->tokens[$owner]['code']]) === true + && isset($this->tokens[$i]['parenthesis_closer']) === true + ) { + // If we get into here, then we opened a parenthesis for + // a scope (eg. an if or else if) so we need to update the + // start of the line so that when we check to see + // if the closing parenthesis is more than n lines away from + // the statement, we check from the closing parenthesis. + $startLine = $this->tokens[$this->tokens[$i]['parenthesis_closer']]['line']; + } + } + } else if ($tokenType === T_OPEN_CURLY_BRACKET && $opener !== null) { + // We opened something that we don't have a scope opener for. + // Examples of this are curly brackets for string offsets etc. + // We want to ignore this so that we don't have an invalid scope + // map. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace *'.PHP_EOL; + } + + $ignore++; + } else if ($tokenType === T_CLOSE_CURLY_BRACKET && $ignore > 0) { + // We found the end token for the opener we were ignoring. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + } else if ($opener === null + && isset($this->scopeOpeners[$currType]) === true + ) { + // If we still haven't found the opener after 30 lines, + // we're not going to find it, unless we know it requires + // an opener (in which case we better keep looking) or the last + // token was empty (in which case we'll just confirm there is + // more code in this file and not just a big comment). + if ($this->tokens[$i]['line'] >= ($startLine + 30) + && isset(Util\Tokens::$emptyTokens[$this->tokens[($i - 1)]['code']]) === false + ) { + if ($this->scopeOpeners[$currType]['strict'] === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + $lines = ($this->tokens[$i]['line'] - $startLine); + echo str_repeat("\t", $depth); + echo "=> Still looking for $stackPtr:$type scope opener after $lines lines".PHP_EOL; + } + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return $stackPtr; + } + } + } else if ($opener !== null + && $tokenType !== T_BREAK + && isset($this->endScopeTokens[$tokenType]) === true + ) { + if (isset($this->tokens[$i]['scope_condition']) === false) { + if ($ignore > 0) { + // We found the end token for the opener we were ignoring. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + } else { + // We found a token that closes the scope but it doesn't + // have a condition, so it belongs to another token and + // our token doesn't have a closer, so pretend this is + // the closer. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found (unexpected) scope closer for $stackPtr:$type".PHP_EOL; + } + + foreach ([$stackPtr, $opener] as $token) { + $this->tokens[$token]['scope_condition'] = $stackPtr; + $this->tokens[$token]['scope_opener'] = $opener; + $this->tokens[$token]['scope_closer'] = $i; + } + + return ($i - 1); + }//end if + }//end if + }//end if + }//end for + + return $stackPtr; + + }//end recurseScopeMap() + + + /** + * Constructs the level map. + * + * The level map adds a 'level' index to each token which indicates the + * depth that a token within a set of scope blocks. It also adds a + * 'conditions' index which is an array of the scope conditions that opened + * each of the scopes - position 0 being the first scope opener. + * + * @return void + */ + private function createLevelMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START LEVEL MAP ***".PHP_EOL; + } + + $this->numTokens = count($this->tokens); + $level = 0; + $conditions = []; + $lastOpener = null; + $openers = []; + + for ($i = 0; $i < $this->numTokens; $i++) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $line = $this->tokens[$i]['line']; + $len = $this->tokens[$i]['length']; + $col = $this->tokens[$i]['column']; + + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", ($level + 1)); + echo "Process token $i on line $line [col:$col;len:$len;lvl:$level;"; + if (empty($conditions) !== true) { + $conditionString = 'conds;'; + foreach ($conditions as $condition) { + $conditionString .= Util\Tokens::tokenName($condition).','; + } + + echo rtrim($conditionString, ',').';'; + } + + echo "]: $type => $content".PHP_EOL; + }//end if + + $this->tokens[$i]['level'] = $level; + $this->tokens[$i]['conditions'] = $conditions; + + if (isset($this->tokens[$i]['scope_condition']) === true) { + // Check to see if this token opened the scope. + if ($this->tokens[$i]['scope_opener'] === $i) { + $stackPtr = $this->tokens[$i]['scope_condition']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", ($level + 1)); + echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + } + + $stackPtr = $this->tokens[$i]['scope_condition']; + + // If we find a scope opener that has a shared closer, + // then we need to go back over the condition map that we + // just created and fix ourselves as we just added some + // conditions where there was none. This happens for T_CASE + // statements that are using the same break statement. + if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $this->tokens[$i]['scope_closer']) { + // This opener shares its closer with the previous opener, + // but we still need to check if the two openers share their + // closer with each other directly (like CASE and DEFAULT) + // or if they are just sharing because one doesn't have a + // closer (like CASE with no BREAK using a SWITCHes closer). + $thisType = $this->tokens[$this->tokens[$i]['scope_condition']]['code']; + $opener = $this->tokens[$lastOpener]['scope_condition']; + + $isShared = isset($this->scopeOpeners[$thisType]['with'][$this->tokens[$opener]['code']]); + + reset($this->scopeOpeners[$thisType]['end']); + reset($this->scopeOpeners[$this->tokens[$opener]['code']]['end']); + $sameEnd = (current($this->scopeOpeners[$thisType]['end']) === current($this->scopeOpeners[$this->tokens[$opener]['code']]['end'])); + + if ($isShared === true && $sameEnd === true) { + $badToken = $opener; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$badToken]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* shared closer, cleaning up $badToken:$type *".PHP_EOL; + } + + for ($x = $this->tokens[$i]['scope_condition']; $x <= $i; $x++) { + $oldConditions = $this->tokens[$x]['conditions']; + $oldLevel = $this->tokens[$x]['level']; + $this->tokens[$x]['level']--; + unset($this->tokens[$x]['conditions'][$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Util\Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Util\Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + $newLevel = $this->tokens[$x]['level']; + echo str_repeat("\t", ($level + 1)); + echo "* cleaned $x:$type *".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + }//end if + }//end for + + unset($conditions[$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$badToken]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* token $badToken:$type removed from conditions array *".PHP_EOL; + } + + unset($openers[$lastOpener]); + + $level--; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 2)); + echo '* level decreased *'.PHP_EOL; + } + }//end if + }//end if + + $level++; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 1)); + echo '* level increased *'.PHP_EOL; + } + + $conditions[$stackPtr] = $this->tokens[$stackPtr]['code']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* token $stackPtr:$type added to conditions array *".PHP_EOL; + } + + $lastOpener = $this->tokens[$i]['scope_opener']; + if ($lastOpener !== null) { + $openers[$lastOpener] = $lastOpener; + } + } else if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $i) { + foreach (array_reverse($openers) as $opener) { + if ($this->tokens[$opener]['scope_closer'] === $i) { + $oldOpener = array_pop($openers); + if (empty($openers) === false) { + $lastOpener = array_pop($openers); + $openers[$lastOpener] = $lastOpener; + } else { + $lastOpener = null; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$oldOpener]['type']; + echo str_repeat("\t", ($level + 1)); + echo "=> Found scope closer for $oldOpener:$type".PHP_EOL; + } + + $oldCondition = array_pop($conditions); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 1)); + echo '* token '.Util\Tokens::tokenName($oldCondition).' removed from conditions array *'.PHP_EOL; + } + + // Make sure this closer actually belongs to us. + // Either the condition also has to think this is the + // closer, or it has to allow sharing with us. + $condition = $this->tokens[$this->tokens[$i]['scope_condition']]['code']; + if ($condition !== $oldCondition) { + if (isset($this->scopeOpeners[$oldCondition]['with'][$condition]) === false) { + $badToken = $this->tokens[$oldOpener]['scope_condition']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Util\Tokens::tokenName($oldCondition); + echo str_repeat("\t", ($level + 1)); + echo "* scope closer was bad, cleaning up $badToken:$type *".PHP_EOL; + } + + for ($x = ($oldOpener + 1); $x <= $i; $x++) { + $oldConditions = $this->tokens[$x]['conditions']; + $oldLevel = $this->tokens[$x]['level']; + $this->tokens[$x]['level']--; + unset($this->tokens[$x]['conditions'][$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Util\Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Util\Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + $newLevel = $this->tokens[$x]['level']; + echo str_repeat("\t", ($level + 1)); + echo "* cleaned $x:$type *".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + }//end if + }//end for + }//end if + }//end if + + $level--; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 2)); + echo '* level decreased *'.PHP_EOL; + } + + $this->tokens[$i]['level'] = $level; + $this->tokens[$i]['conditions'] = $conditions; + }//end if + }//end foreach + }//end if + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END LEVEL MAP ***".PHP_EOL; + } + + }//end createLevelMap() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Util/Cache.php b/kirki-composer/squizlabs/php_codesniffer/src/Util/Cache.php new file mode 100644 index 000000000..68abef59c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Util/Cache.php @@ -0,0 +1,351 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; + +class Cache +{ + + /** + * The filesystem location of the cache file. + * + * @var void + */ + private static $path = ''; + + /** + * The cached data. + * + * @var array + */ + private static $cache = []; + + + /** + * Loads existing cache data for the run, if any. + * + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public static function load(Ruleset $ruleset, Config $config) + { + // Look at every loaded sniff class so far and use their file contents + // to generate a hash for the code used during the run. + // At this point, the loaded class list contains the core PHPCS code + // and all sniffs that have been loaded as part of the run. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL."\tGenerating loaded file list for code hash".PHP_EOL; + } + + $codeHashFiles = []; + + $classes = array_keys(Autoload::getLoadedClasses()); + sort($classes); + + $installDir = dirname(__DIR__); + $installDirLen = strlen($installDir); + $standardDir = $installDir.DIRECTORY_SEPARATOR.'Standards'; + $standardDirLen = strlen($standardDir); + foreach ($classes as $file) { + if (substr($file, 0, $standardDirLen) !== $standardDir) { + if (substr($file, 0, $installDirLen) === $installDir) { + // We are only interested in sniffs here. + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> external file: $file".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> internal sniff: $file".PHP_EOL; + } + + $codeHashFiles[] = $file; + } + + // Add the content of the used rulesets to the hash so that sniff setting + // changes in the ruleset invalidate the cache. + $rulesets = $ruleset->paths; + sort($rulesets); + foreach ($rulesets as $file) { + if (substr($file, 0, $standardDirLen) !== $standardDir) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> external ruleset: $file".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> internal ruleset: $file".PHP_EOL; + } + + $codeHashFiles[] = $file; + } + + // Go through the core PHPCS code and add those files to the file + // hash. This ensures that core PHPCS changes will also invalidate the cache. + // Note that we ignore sniffs here, and any files that don't affect + // the outcome of the run. + $di = new \RecursiveDirectoryIterator( + $installDir, + (\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS) + ); + $filter = new \RecursiveCallbackFilterIterator( + $di, + function ($file, $key, $iterator) { + // Skip non-php files. + $filename = $file->getFilename(); + if ($file->isFile() === true && substr($filename, -4) !== '.php') { + return false; + } + + $filePath = Common::realpath($key); + if ($filePath === false) { + return false; + } + + if ($iterator->hasChildren() === true + && ($filename === 'Standards' + || $filename === 'Exceptions' + || $filename === 'Reports' + || $filename === 'Generators') + ) { + return false; + } + + return true; + } + ); + + $iterator = new \RecursiveIteratorIterator($filter); + foreach ($iterator as $file) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> core file: $file".PHP_EOL; + } + + $codeHashFiles[] = $file->getPathname(); + } + + $codeHash = ''; + sort($codeHashFiles); + foreach ($codeHashFiles as $file) { + $codeHash .= md5_file($file); + } + + $codeHash = md5($codeHash); + + // Along with the code hash, use various settings that can affect + // the results of a run to create a new hash. This hash will be used + // in the cache file name. + $rulesetHash = md5(var_export($ruleset->ignorePatterns, true).var_export($ruleset->includePatterns, true)); + $phpExtensionsHash = md5(var_export(get_loaded_extensions(), true)); + $configData = [ + 'phpVersion' => PHP_VERSION_ID, + 'phpExtensions' => $phpExtensionsHash, + 'tabWidth' => $config->tabWidth, + 'encoding' => $config->encoding, + 'recordErrors' => $config->recordErrors, + 'annotations' => $config->annotations, + 'configData' => Config::getAllConfigData(), + 'codeHash' => $codeHash, + 'rulesetHash' => $rulesetHash, + ]; + + $configString = var_export($configData, true); + $cacheHash = substr(sha1($configString), 0, 12); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\tGenerating cache key data".PHP_EOL; + foreach ($configData as $key => $value) { + if (is_array($value) === true) { + echo "\t\t=> $key:".PHP_EOL; + foreach ($value as $subKey => $subValue) { + echo "\t\t\t=> $subKey: $subValue".PHP_EOL; + } + + continue; + } + + if ($value === true || $value === false) { + $value = (int) $value; + } + + echo "\t\t=> $key: $value".PHP_EOL; + } + + echo "\t\t=> cacheHash: $cacheHash".PHP_EOL; + }//end if + + if ($config->cacheFile !== null) { + $cacheFile = $config->cacheFile; + } else { + // Determine the common paths for all files being checked. + // We can use this to locate an existing cache file, or to + // determine where to create a new one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\tChecking possible cache file paths".PHP_EOL; + } + + $paths = []; + foreach ($config->files as $file) { + $file = Common::realpath($file); + while ($file !== DIRECTORY_SEPARATOR) { + if (isset($paths[$file]) === false) { + $paths[$file] = 1; + } else { + $paths[$file]++; + } + + $lastFile = $file; + $file = dirname($file); + if ($file === $lastFile) { + // Just in case something went wrong, + // we don't want to end up in an infinite loop. + break; + } + } + } + + ksort($paths); + $paths = array_reverse($paths); + + $numFiles = count($config->files); + + $cacheFile = null; + $cacheDir = getenv('XDG_CACHE_HOME'); + if ($cacheDir === false || is_dir($cacheDir) === false) { + $cacheDir = sys_get_temp_dir(); + } + + foreach ($paths as $file => $count) { + if ($count !== $numFiles) { + unset($paths[$file]); + continue; + } + + $fileHash = substr(sha1($file), 0, 12); + $testFile = $cacheDir.DIRECTORY_SEPARATOR."phpcs.$fileHash.$cacheHash.cache"; + if ($cacheFile === null) { + // This will be our default location if we can't find + // an existing file. + $cacheFile = $testFile; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> $testFile".PHP_EOL; + echo "\t\t\t * based on shared location: $file *".PHP_EOL; + } + + if (file_exists($testFile) === true) { + $cacheFile = $testFile; + break; + } + }//end foreach + + if ($cacheFile === null) { + // Unlikely, but just in case $paths is empty for some reason. + $cacheFile = $cacheDir.DIRECTORY_SEPARATOR."phpcs.$cacheHash.cache"; + } + }//end if + + self::$path = $cacheFile; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t=> Using cache file: ".self::$path.PHP_EOL; + } + + if (file_exists(self::$path) === true) { + self::$cache = json_decode(file_get_contents(self::$path), true); + + // Verify the contents of the cache file. + if (self::$cache['config'] !== $configData) { + self::$cache = []; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* cache was invalid and has been cleared *".PHP_EOL; + } + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* cache file does not exist *".PHP_EOL; + } + + self::$cache['config'] = $configData; + + }//end load() + + + /** + * Saves the current cache to the filesystem. + * + * @return void + */ + public static function save() + { + file_put_contents(self::$path, json_encode(self::$cache)); + + }//end save() + + + /** + * Retrieves a single entry from the cache. + * + * @param string $key The key of the data to get. If NULL, + * everything in the cache is returned. + * + * @return mixed + */ + public static function get($key=null) + { + if ($key === null) { + return self::$cache; + } + + if (isset(self::$cache[$key]) === true) { + return self::$cache[$key]; + } + + return false; + + }//end get() + + + /** + * Retrieves a single entry from the cache. + * + * @param string $key The key of the data to set. If NULL, + * sets the entire cache. + * @param mixed $value The value to set. + * + * @return void + */ + public static function set($key, $value) + { + if ($key === null) { + self::$cache = $value; + } else { + self::$cache[$key] = $value; + } + + }//end set() + + + /** + * Retrieves the number of cache entries. + * + * @return int + */ + public static function getSize() + { + return (count(self::$cache) - 1); + + }//end getSize() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Util/Common.php b/kirki-composer/squizlabs/php_codesniffer/src/Util/Common.php new file mode 100644 index 000000000..caf4db772 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Util/Common.php @@ -0,0 +1,570 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +class Common +{ + + /** + * An array of variable types for param/var we will check. + * + * @var string[] + */ + public static $allowedTypes = [ + 'array', + 'boolean', + 'float', + 'integer', + 'mixed', + 'object', + 'string', + 'resource', + 'callable', + ]; + + + /** + * Return TRUE if the path is a PHAR file. + * + * @param string $path The path to use. + * + * @return mixed + */ + public static function isPharFile($path) + { + if (strpos($path, 'phar://') === 0) { + return true; + } + + return false; + + }//end isPharFile() + + + /** + * Checks if a file is readable. + * + * Addresses PHP bug related to reading files from network drives on Windows. + * e.g. when using WSL2. + * + * @param string $path The path to the file. + * + * @return boolean + */ + public static function isReadable($path) + { + if (@is_readable($path) === true) { + return true; + } + + if (@file_exists($path) === true && @is_file($path) === true) { + $f = @fopen($path, 'rb'); + if (fclose($f) === true) { + return true; + } + } + + return false; + + }//end isReadable() + + + /** + * CodeSniffer alternative for realpath. + * + * Allows for PHAR support. + * + * @param string $path The path to use. + * + * @return mixed + */ + public static function realpath($path) + { + // Support the path replacement of ~ with the user's home directory. + if (substr($path, 0, 2) === '~/') { + $homeDir = getenv('HOME'); + if ($homeDir !== false) { + $path = $homeDir.substr($path, 1); + } + } + + // Check for process substitution. + if (strpos($path, '/dev/fd') === 0) { + return str_replace('/dev/fd', 'php://fd', $path); + } + + // No extra work needed if this is not a phar file. + if (self::isPharFile($path) === false) { + return realpath($path); + } + + // Before trying to break down the file path, + // check if it exists first because it will mostly not + // change after running the below code. + if (file_exists($path) === true) { + return $path; + } + + $phar = \Phar::running(false); + $extra = str_replace('phar://'.$phar, '', $path); + $path = realpath($phar); + if ($path === false) { + return false; + } + + $path = 'phar://'.$path.$extra; + if (file_exists($path) === true) { + return $path; + } + + return false; + + }//end realpath() + + + /** + * Removes a base path from the front of a file path. + * + * @param string $path The path of the file. + * @param string $basepath The base path to remove. This should not end + * with a directory separator. + * + * @return string + */ + public static function stripBasepath($path, $basepath) + { + if (empty($basepath) === true) { + return $path; + } + + $basepathLen = strlen($basepath); + if (substr($path, 0, $basepathLen) === $basepath) { + $path = substr($path, $basepathLen); + } + + $path = ltrim($path, DIRECTORY_SEPARATOR); + if ($path === '') { + $path = '.'; + } + + return $path; + + }//end stripBasepath() + + + /** + * Detects the EOL character being used in a string. + * + * @param string $contents The contents to check. + * + * @return string + */ + public static function detectLineEndings($contents) + { + if (preg_match("/\r\n?|\n/", $contents, $matches) !== 1) { + // Assume there are no newlines. + $eolChar = "\n"; + } else { + $eolChar = $matches[0]; + } + + return $eolChar; + + }//end detectLineEndings() + + + /** + * Check if STDIN is a TTY. + * + * @return boolean + */ + public static function isStdinATTY() + { + // The check is slow (especially calling `tty`) so we static + // cache the result. + static $isTTY = null; + + if ($isTTY !== null) { + return $isTTY; + } + + if (defined('STDIN') === false) { + return false; + } + + // If PHP has the POSIX extensions we will use them. + if (function_exists('posix_isatty') === true) { + $isTTY = (posix_isatty(STDIN) === true); + return $isTTY; + } + + // Next try is detecting whether we have `tty` installed and use that. + if (defined('PHP_WINDOWS_VERSION_PLATFORM') === true) { + $devnull = 'NUL'; + $which = 'where'; + } else { + $devnull = '/dev/null'; + $which = 'which'; + } + + $tty = trim(shell_exec("$which tty 2> $devnull")); + if (empty($tty) === false) { + exec("tty -s 2> $devnull", $output, $returnValue); + $isTTY = ($returnValue === 0); + return $isTTY; + } + + // Finally we will use fstat. The solution borrowed from + // https://stackoverflow.com/questions/11327367/detect-if-a-php-script-is-being-run-interactively-or-not + // This doesn't work on Mingw/Cygwin/... using Mintty but they + // have `tty` installed. + $type = [ + 'S_IFMT' => 0170000, + 'S_IFIFO' => 0010000, + ]; + + $stat = fstat(STDIN); + $mode = ($stat['mode'] & $type['S_IFMT']); + $isTTY = ($mode !== $type['S_IFIFO']); + + return $isTTY; + + }//end isStdinATTY() + + + /** + * Escape a path to a system command. + * + * @param string $cmd The path to the system command. + * + * @return string + */ + public static function escapeshellcmd($cmd) + { + $cmd = escapeshellcmd($cmd); + + if (stripos(PHP_OS, 'WIN') === 0) { + // Spaces are not escaped by escapeshellcmd on Windows, but need to be + // for the command to be able to execute. + $cmd = preg_replace('`(? 0) { + return false; + } + + if ($strict === true) { + // Check that there are not two capital letters next to each other. + $length = strlen($string); + $lastCharWasCaps = $classFormat; + + for ($i = 1; $i < $length; $i++) { + $ascii = ord($string[$i]); + if ($ascii >= 48 && $ascii <= 57) { + // The character is a number, so it cant be a capital. + $isCaps = false; + } else { + if (strtoupper($string[$i]) === $string[$i]) { + $isCaps = true; + } else { + $isCaps = false; + } + } + + if ($isCaps === true && $lastCharWasCaps === true) { + return false; + } + + $lastCharWasCaps = $isCaps; + } + }//end if + + return true; + + }//end isCamelCaps() + + + /** + * Returns true if the specified string is in the underscore caps format. + * + * @param string $string The string to verify. + * + * @return boolean + */ + public static function isUnderscoreName($string) + { + // If there are space in the name, it can't be valid. + if (strpos($string, ' ') !== false) { + return false; + } + + $validName = true; + $nameBits = explode('_', $string); + + if (preg_match('|^[A-Z]|', $string) === 0) { + // Name does not begin with a capital letter. + $validName = false; + } else { + foreach ($nameBits as $bit) { + if ($bit === '') { + continue; + } + + if ($bit[0] !== strtoupper($bit[0])) { + $validName = false; + break; + } + } + } + + return $validName; + + }//end isUnderscoreName() + + + /** + * Returns a valid variable type for param/var tags. + * + * If type is not one of the standard types, it must be a custom type. + * Returns the correct type name suggestion if type name is invalid. + * + * @param string $varType The variable type to process. + * + * @return string + */ + public static function suggestType($varType) + { + if ($varType === '') { + return ''; + } + + if (in_array($varType, self::$allowedTypes, true) === true) { + return $varType; + } else { + $lowerVarType = strtolower($varType); + switch ($lowerVarType) { + case 'bool': + case 'boolean': + return 'boolean'; + case 'double': + case 'real': + case 'float': + return 'float'; + case 'int': + case 'integer': + return 'integer'; + case 'array()': + case 'array': + return 'array'; + }//end switch + + if (strpos($lowerVarType, 'array(') !== false) { + // Valid array declaration: + // array, array(type), array(type1 => type2). + $matches = []; + $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i'; + if (preg_match($pattern, $varType, $matches) !== 0) { + $type1 = ''; + if (isset($matches[1]) === true) { + $type1 = $matches[1]; + } + + $type2 = ''; + if (isset($matches[3]) === true) { + $type2 = $matches[3]; + } + + $type1 = self::suggestType($type1); + $type2 = self::suggestType($type2); + if ($type2 !== '') { + $type2 = ' => '.$type2; + } + + return "array($type1$type2)"; + } else { + return 'array'; + }//end if + } else if (in_array($lowerVarType, self::$allowedTypes, true) === true) { + // A valid type, but not lower cased. + return $lowerVarType; + } else { + // Must be a custom type name. + return $varType; + }//end if + }//end if + + }//end suggestType() + + + /** + * Given a sniff class name, returns the code for the sniff. + * + * @param string $sniffClass The fully qualified sniff class name. + * + * @return string + */ + public static function getSniffCode($sniffClass) + { + $parts = explode('\\', $sniffClass); + $sniff = array_pop($parts); + + if (substr($sniff, -5) === 'Sniff') { + // Sniff class name. + $sniff = substr($sniff, 0, -5); + } else { + // Unit test class name. + $sniff = substr($sniff, 0, -8); + } + + $category = array_pop($parts); + $sniffDir = array_pop($parts); + $standard = array_pop($parts); + $code = $standard.'.'.$category.'.'.$sniff; + return $code; + + }//end getSniffCode() + + + /** + * Removes project-specific information from a sniff class name. + * + * @param string $sniffClass The fully qualified sniff class name. + * + * @return string + */ + public static function cleanSniffClass($sniffClass) + { + $newName = strtolower($sniffClass); + + $sniffPos = strrpos($newName, '\sniffs\\'); + if ($sniffPos === false) { + // Nothing we can do as it isn't in a known format. + return $newName; + } + + $end = (strlen($newName) - $sniffPos + 1); + $start = strrpos($newName, '\\', ($end * -1)); + + if ($start === false) { + // Nothing needs to be cleaned. + return $newName; + } + + $newName = substr($newName, ($start + 1)); + return $newName; + + }//end cleanSniffClass() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Util/Standards.php b/kirki-composer/squizlabs/php_codesniffer/src/Util/Standards.php new file mode 100644 index 000000000..65e5d6cb3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Util/Standards.php @@ -0,0 +1,339 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use PHP_CodeSniffer\Config; + +class Standards +{ + + + /** + * Get a list of paths where standards are installed. + * + * Unresolvable relative paths will be excluded from the results. + * + * @return array + */ + public static function getInstalledStandardPaths() + { + $ds = DIRECTORY_SEPARATOR; + + $installedPaths = [dirname(dirname(__DIR__)).$ds.'src'.$ds.'Standards']; + $configPaths = Config::getConfigData('installed_paths'); + if ($configPaths !== null) { + $installedPaths = array_merge($installedPaths, explode(',', $configPaths)); + } + + $resolvedInstalledPaths = []; + foreach ($installedPaths as $installedPath) { + if (substr($installedPath, 0, 1) === '.') { + $installedPath = Common::realPath(__DIR__.$ds.'..'.$ds.'..'.$ds.$installedPath); + if ($installedPath === false) { + continue; + } + } + + $resolvedInstalledPaths[] = $installedPath; + } + + return $resolvedInstalledPaths; + + }//end getInstalledStandardPaths() + + + /** + * Get the details of all coding standards installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a Sniffs subdirectory. + * + * The details returned for each standard are: + * - path: the path to the coding standard's main directory + * - name: the name of the coding standard, as sourced from the ruleset.xml file + * - namespace: the namespace used by the coding standard, as sourced from the ruleset.xml file + * + * If you only need the paths to the installed standards, + * use getInstalledStandardPaths() instead as it performs less work to + * retrieve coding standard names. + * + * @param boolean $includeGeneric If true, the special "Generic" + * coding standard will be included + * if installed. + * @param string $standardsDir A specific directory to look for standards + * in. If not specified, PHP_CodeSniffer will + * look in its default locations. + * + * @return array + * @see getInstalledStandardPaths() + */ + public static function getInstalledStandardDetails( + $includeGeneric=false, + $standardsDir='' + ) { + $rulesets = []; + + if ($standardsDir === '') { + $installedPaths = self::getInstalledStandardPaths(); + } else { + $installedPaths = [$standardsDir]; + } + + foreach ($installedPaths as $standardsDir) { + // Check if the installed dir is actually a standard itself. + $csFile = $standardsDir.'/ruleset.xml'; + if (is_file($csFile) === true) { + $rulesets[] = $csFile; + continue; + } + + if (is_dir($standardsDir) === false) { + continue; + } + + $di = new \DirectoryIterator($standardsDir); + foreach ($di as $file) { + if ($file->isDir() === true && $file->isDot() === false) { + $filename = $file->getFilename(); + + // Ignore the special "Generic" standard. + if ($includeGeneric === false && $filename === 'Generic') { + continue; + } + + // Valid coding standard dirs include a ruleset. + $csFile = $file->getPathname().'/ruleset.xml'; + if (is_file($csFile) === true) { + $rulesets[] = $csFile; + } + } + } + }//end foreach + + $installedStandards = []; + + foreach ($rulesets as $rulesetPath) { + $ruleset = @simplexml_load_string(file_get_contents($rulesetPath)); + if ($ruleset === false) { + continue; + } + + $standardName = (string) $ruleset['name']; + $dirname = basename(dirname($rulesetPath)); + + if (isset($ruleset['namespace']) === true) { + $namespace = (string) $ruleset['namespace']; + } else { + $namespace = $dirname; + } + + $installedStandards[$dirname] = [ + 'path' => dirname($rulesetPath), + 'name' => $standardName, + 'namespace' => $namespace, + ]; + }//end foreach + + return $installedStandards; + + }//end getInstalledStandardDetails() + + + /** + * Get a list of all coding standards installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a Sniffs subdirectory. + * + * @param boolean $includeGeneric If true, the special "Generic" + * coding standard will be included + * if installed. + * @param string $standardsDir A specific directory to look for standards + * in. If not specified, PHP_CodeSniffer will + * look in its default locations. + * + * @return array + * @see isInstalledStandard() + */ + public static function getInstalledStandards( + $includeGeneric=false, + $standardsDir='' + ) { + $installedStandards = []; + + if ($standardsDir === '') { + $installedPaths = self::getInstalledStandardPaths(); + } else { + $installedPaths = [$standardsDir]; + } + + foreach ($installedPaths as $standardsDir) { + // Check if the installed dir is actually a standard itself. + $csFile = $standardsDir.'/ruleset.xml'; + if (is_file($csFile) === true) { + $basename = basename($standardsDir); + $installedStandards[$basename] = $basename; + continue; + } + + if (is_dir($standardsDir) === false) { + // Doesn't exist. + continue; + } + + $di = new \DirectoryIterator($standardsDir); + $standardsInDir = []; + foreach ($di as $file) { + if ($file->isDir() === true && $file->isDot() === false) { + $filename = $file->getFilename(); + + // Ignore the special "Generic" standard. + if ($includeGeneric === false && $filename === 'Generic') { + continue; + } + + // Valid coding standard dirs include a ruleset. + $csFile = $file->getPathname().'/ruleset.xml'; + if (is_file($csFile) === true) { + $standardsInDir[$filename] = $filename; + } + } + } + + natsort($standardsInDir); + $installedStandards += $standardsInDir; + }//end foreach + + return $installedStandards; + + }//end getInstalledStandards() + + + /** + * Determine if a standard is installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a ruleset.xml file. + * + * @param string $standard The name of the coding standard. + * + * @return boolean + * @see getInstalledStandards() + */ + public static function isInstalledStandard($standard) + { + $path = self::getInstalledStandardPath($standard); + if ($path !== null && strpos($path, 'ruleset.xml') !== false) { + return true; + } else { + // This could be a custom standard, installed outside our + // standards directory. + $standard = Common::realPath($standard); + if ($standard === false) { + return false; + } + + // Might be an actual ruleset file itUtil. + // If it has an XML extension, let's at least try it. + if (is_file($standard) === true + && (substr(strtolower($standard), -4) === '.xml' + || substr(strtolower($standard), -9) === '.xml.dist') + ) { + return true; + } + + // If it is a directory with a ruleset.xml file in it, + // it is a standard. + $ruleset = rtrim($standard, ' /\\').DIRECTORY_SEPARATOR.'ruleset.xml'; + if (is_file($ruleset) === true) { + return true; + } + }//end if + + return false; + + }//end isInstalledStandard() + + + /** + * Return the path of an installed coding standard. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a ruleset.xml file. + * + * @param string $standard The name of the coding standard. + * + * @return string|null + */ + public static function getInstalledStandardPath($standard) + { + if (strpos($standard, '.') !== false) { + return null; + } + + $installedPaths = self::getInstalledStandardPaths(); + foreach ($installedPaths as $installedPath) { + $standardPath = $installedPath.DIRECTORY_SEPARATOR.$standard; + if (file_exists($standardPath) === false) { + if (basename($installedPath) !== $standard) { + continue; + } + + $standardPath = $installedPath; + } + + $path = Common::realpath($standardPath.DIRECTORY_SEPARATOR.'ruleset.xml'); + + if ($path !== false && is_file($path) === true) { + return $path; + } else if (Common::isPharFile($standardPath) === true) { + $path = Common::realpath($standardPath); + if ($path !== false) { + return $path; + } + } + }//end foreach + + return null; + + }//end getInstalledStandardPath() + + + /** + * Prints out a list of installed coding standards. + * + * @return void + */ + public static function printInstalledStandards() + { + $installedStandards = self::getInstalledStandards(); + $numStandards = count($installedStandards); + + if ($numStandards === 0) { + echo 'No coding standards are installed.'.PHP_EOL; + } else { + $lastStandard = array_pop($installedStandards); + if ($numStandards === 1) { + echo "The only coding standard installed is $lastStandard".PHP_EOL; + } else { + $standardList = implode(', ', $installedStandards); + $standardList .= ' and '.$lastStandard; + echo 'The installed coding standards are '.$standardList.PHP_EOL; + } + } + + }//end printInstalledStandards() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Util/Timing.php b/kirki-composer/squizlabs/php_codesniffer/src/Util/Timing.php new file mode 100644 index 000000000..95ee85216 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Util/Timing.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +class Timing +{ + + /** + * The start time of the run. + * + * @var float + */ + private static $startTime; + + /** + * Used to make sure we only print the run time once per run. + * + * @var boolean + */ + private static $printed = false; + + + /** + * Start recording time for the run. + * + * @return void + */ + public static function startTiming() + { + + self::$startTime = microtime(true); + + }//end startTiming() + + + /** + * Print information about the run. + * + * @param boolean $force If TRUE, prints the output even if it has + * already been printed during the run. + * + * @return void + */ + public static function printRunTime($force=false) + { + if ($force === false && self::$printed === true) { + // A double call. + return; + } + + if (self::$startTime === null) { + // Timing was never started. + return; + } + + $time = ((microtime(true) - self::$startTime) * 1000); + + if ($time > 60000) { + $mins = floor($time / 60000); + $secs = round((fmod($time, 60000) / 1000), 2); + $time = $mins.' mins'; + if ($secs !== 0) { + $time .= ", $secs secs"; + } + } else if ($time > 1000) { + $time = round(($time / 1000), 2).' secs'; + } else { + $time = round($time).'ms'; + } + + $mem = round((memory_get_peak_usage(true) / (1024 * 1024)), 2).'MB'; + echo "Time: $time; Memory: $mem".PHP_EOL.PHP_EOL; + + self::$printed = true; + + }//end printRunTime() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/src/Util/Tokens.php b/kirki-composer/squizlabs/php_codesniffer/src/Util/Tokens.php new file mode 100644 index 000000000..1208e4f05 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/src/Util/Tokens.php @@ -0,0 +1,809 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +define('T_NONE', 'PHPCS_T_NONE'); +define('T_OPEN_CURLY_BRACKET', 'PHPCS_T_OPEN_CURLY_BRACKET'); +define('T_CLOSE_CURLY_BRACKET', 'PHPCS_T_CLOSE_CURLY_BRACKET'); +define('T_OPEN_SQUARE_BRACKET', 'PHPCS_T_OPEN_SQUARE_BRACKET'); +define('T_CLOSE_SQUARE_BRACKET', 'PHPCS_T_CLOSE_SQUARE_BRACKET'); +define('T_OPEN_PARENTHESIS', 'PHPCS_T_OPEN_PARENTHESIS'); +define('T_CLOSE_PARENTHESIS', 'PHPCS_T_CLOSE_PARENTHESIS'); +define('T_COLON', 'PHPCS_T_COLON'); +define('T_NULLABLE', 'PHPCS_T_NULLABLE'); +define('T_STRING_CONCAT', 'PHPCS_T_STRING_CONCAT'); +define('T_INLINE_THEN', 'PHPCS_T_INLINE_THEN'); +define('T_INLINE_ELSE', 'PHPCS_T_INLINE_ELSE'); +define('T_NULL', 'PHPCS_T_NULL'); +define('T_FALSE', 'PHPCS_T_FALSE'); +define('T_TRUE', 'PHPCS_T_TRUE'); +define('T_SEMICOLON', 'PHPCS_T_SEMICOLON'); +define('T_EQUAL', 'PHPCS_T_EQUAL'); +define('T_MULTIPLY', 'PHPCS_T_MULTIPLY'); +define('T_DIVIDE', 'PHPCS_T_DIVIDE'); +define('T_PLUS', 'PHPCS_T_PLUS'); +define('T_MINUS', 'PHPCS_T_MINUS'); +define('T_MODULUS', 'PHPCS_T_MODULUS'); +define('T_BITWISE_AND', 'PHPCS_T_BITWISE_AND'); +define('T_BITWISE_OR', 'PHPCS_T_BITWISE_OR'); +define('T_BITWISE_XOR', 'PHPCS_T_BITWISE_XOR'); +define('T_BITWISE_NOT', 'PHPCS_T_BITWISE_NOT'); +define('T_ARRAY_HINT', 'PHPCS_T_ARRAY_HINT'); +define('T_GREATER_THAN', 'PHPCS_T_GREATER_THAN'); +define('T_LESS_THAN', 'PHPCS_T_LESS_THAN'); +define('T_BOOLEAN_NOT', 'PHPCS_T_BOOLEAN_NOT'); +define('T_SELF', 'PHPCS_T_SELF'); +define('T_PARENT', 'PHPCS_T_PARENT'); +define('T_DOUBLE_QUOTED_STRING', 'PHPCS_T_DOUBLE_QUOTED_STRING'); +define('T_COMMA', 'PHPCS_T_COMMA'); +define('T_HEREDOC', 'PHPCS_T_HEREDOC'); +define('T_PROTOTYPE', 'PHPCS_T_PROTOTYPE'); +define('T_THIS', 'PHPCS_T_THIS'); +define('T_REGULAR_EXPRESSION', 'PHPCS_T_REGULAR_EXPRESSION'); +define('T_PROPERTY', 'PHPCS_T_PROPERTY'); +define('T_LABEL', 'PHPCS_T_LABEL'); +define('T_OBJECT', 'PHPCS_T_OBJECT'); +define('T_CLOSE_OBJECT', 'PHPCS_T_CLOSE_OBJECT'); +define('T_COLOUR', 'PHPCS_T_COLOUR'); +define('T_HASH', 'PHPCS_T_HASH'); +define('T_URL', 'PHPCS_T_URL'); +define('T_STYLE', 'PHPCS_T_STYLE'); +define('T_ASPERAND', 'PHPCS_T_ASPERAND'); +define('T_DOLLAR', 'PHPCS_T_DOLLAR'); +define('T_TYPEOF', 'PHPCS_T_TYPEOF'); +define('T_CLOSURE', 'PHPCS_T_CLOSURE'); +define('T_ANON_CLASS', 'PHPCS_T_ANON_CLASS'); +define('T_BACKTICK', 'PHPCS_T_BACKTICK'); +define('T_START_NOWDOC', 'PHPCS_T_START_NOWDOC'); +define('T_NOWDOC', 'PHPCS_T_NOWDOC'); +define('T_END_NOWDOC', 'PHPCS_T_END_NOWDOC'); +define('T_OPEN_SHORT_ARRAY', 'PHPCS_T_OPEN_SHORT_ARRAY'); +define('T_CLOSE_SHORT_ARRAY', 'PHPCS_T_CLOSE_SHORT_ARRAY'); +define('T_GOTO_LABEL', 'PHPCS_T_GOTO_LABEL'); +define('T_BINARY_CAST', 'PHPCS_T_BINARY_CAST'); +define('T_EMBEDDED_PHP', 'PHPCS_T_EMBEDDED_PHP'); +define('T_RETURN_TYPE', 'PHPCS_T_RETURN_TYPE'); +define('T_OPEN_USE_GROUP', 'PHPCS_T_OPEN_USE_GROUP'); +define('T_CLOSE_USE_GROUP', 'PHPCS_T_CLOSE_USE_GROUP'); +define('T_ZSR', 'PHPCS_T_ZSR'); +define('T_ZSR_EQUAL', 'PHPCS_T_ZSR_EQUAL'); +define('T_FN_ARROW', 'PHPCS_T_FN_ARROW'); +define('T_TYPE_UNION', 'PHPCS_T_TYPE_UNION'); +define('T_PARAM_NAME', 'PHPCS_T_PARAM_NAME'); +define('T_MATCH_ARROW', 'PHPCS_T_MATCH_ARROW'); +define('T_MATCH_DEFAULT', 'PHPCS_T_MATCH_DEFAULT'); +define('T_ATTRIBUTE_END', 'PHPCS_T_ATTRIBUTE_END'); +define('T_ENUM_CASE', 'PHPCS_T_ENUM_CASE'); +define('T_TYPE_INTERSECTION', 'PHPCS_T_TYPE_INTERSECTION'); + +// Some PHP 5.5 tokens, replicated for lower versions. +if (defined('T_FINALLY') === false) { + define('T_FINALLY', 'PHPCS_T_FINALLY'); +} + +if (defined('T_YIELD') === false) { + define('T_YIELD', 'PHPCS_T_YIELD'); +} + +// Some PHP 5.6 tokens, replicated for lower versions. +if (defined('T_ELLIPSIS') === false) { + define('T_ELLIPSIS', 'PHPCS_T_ELLIPSIS'); +} + +if (defined('T_POW') === false) { + define('T_POW', 'PHPCS_T_POW'); +} + +if (defined('T_POW_EQUAL') === false) { + define('T_POW_EQUAL', 'PHPCS_T_POW_EQUAL'); +} + +// Some PHP 7 tokens, replicated for lower versions. +if (defined('T_SPACESHIP') === false) { + define('T_SPACESHIP', 'PHPCS_T_SPACESHIP'); +} + +if (defined('T_COALESCE') === false) { + define('T_COALESCE', 'PHPCS_T_COALESCE'); +} + +if (defined('T_COALESCE_EQUAL') === false) { + define('T_COALESCE_EQUAL', 'PHPCS_T_COALESCE_EQUAL'); +} + +if (defined('T_YIELD_FROM') === false) { + define('T_YIELD_FROM', 'PHPCS_T_YIELD_FROM'); +} + +// Some PHP 7.4 tokens, replicated for lower versions. +if (defined('T_BAD_CHARACTER') === false) { + define('T_BAD_CHARACTER', 'PHPCS_T_BAD_CHARACTER'); +} + +if (defined('T_FN') === false) { + define('T_FN', 'PHPCS_T_FN'); +} + +// Some PHP 8.0 tokens, replicated for lower versions. +if (defined('T_NULLSAFE_OBJECT_OPERATOR') === false) { + define('T_NULLSAFE_OBJECT_OPERATOR', 'PHPCS_T_NULLSAFE_OBJECT_OPERATOR'); +} + +if (defined('T_NAME_QUALIFIED') === false) { + define('T_NAME_QUALIFIED', 'PHPCS_T_NAME_QUALIFIED'); +} + +if (defined('T_NAME_FULLY_QUALIFIED') === false) { + define('T_NAME_FULLY_QUALIFIED', 'PHPCS_T_NAME_FULLY_QUALIFIED'); +} + +if (defined('T_NAME_RELATIVE') === false) { + define('T_NAME_RELATIVE', 'PHPCS_T_NAME_RELATIVE'); +} + +if (defined('T_MATCH') === false) { + define('T_MATCH', 'PHPCS_T_MATCH'); +} + +if (defined('T_ATTRIBUTE') === false) { + define('T_ATTRIBUTE', 'PHPCS_T_ATTRIBUTE'); +} + +// Some PHP 8.1 tokens, replicated for lower versions. +if (defined('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG') === false) { + define('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', 'PHPCS_T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG'); +} + +if (defined('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG') === false) { + define('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', 'PHPCS_T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG'); +} + +if (defined('T_READONLY') === false) { + define('T_READONLY', 'PHPCS_T_READONLY'); +} + +if (defined('T_ENUM') === false) { + define('T_ENUM', 'PHPCS_T_ENUM'); +} + +// Tokens used for parsing doc blocks. +define('T_DOC_COMMENT_STAR', 'PHPCS_T_DOC_COMMENT_STAR'); +define('T_DOC_COMMENT_WHITESPACE', 'PHPCS_T_DOC_COMMENT_WHITESPACE'); +define('T_DOC_COMMENT_TAG', 'PHPCS_T_DOC_COMMENT_TAG'); +define('T_DOC_COMMENT_OPEN_TAG', 'PHPCS_T_DOC_COMMENT_OPEN_TAG'); +define('T_DOC_COMMENT_CLOSE_TAG', 'PHPCS_T_DOC_COMMENT_CLOSE_TAG'); +define('T_DOC_COMMENT_STRING', 'PHPCS_T_DOC_COMMENT_STRING'); + +// Tokens used for PHPCS instruction comments. +define('T_PHPCS_ENABLE', 'PHPCS_T_PHPCS_ENABLE'); +define('T_PHPCS_DISABLE', 'PHPCS_T_PHPCS_DISABLE'); +define('T_PHPCS_SET', 'PHPCS_T_PHPCS_SET'); +define('T_PHPCS_IGNORE', 'PHPCS_T_PHPCS_IGNORE'); +define('T_PHPCS_IGNORE_FILE', 'PHPCS_T_PHPCS_IGNORE_FILE'); + +final class Tokens +{ + + /** + * The token weightings. + * + * @var array + */ + public static $weightings = [ + T_CLASS => 1000, + T_INTERFACE => 1000, + T_TRAIT => 1000, + T_ENUM => 1000, + T_NAMESPACE => 1000, + T_FUNCTION => 100, + T_CLOSURE => 100, + + /* + * Conditions. + */ + + T_WHILE => 50, + T_FOR => 50, + T_FOREACH => 50, + T_IF => 50, + T_ELSE => 50, + T_ELSEIF => 50, + T_DO => 50, + T_TRY => 50, + T_CATCH => 50, + T_FINALLY => 50, + T_SWITCH => 50, + T_MATCH => 50, + + T_SELF => 25, + T_PARENT => 25, + + /* + * Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + T_BITWISE_OR => 8, + T_BITWISE_XOR => 8, + + T_MULTIPLY => 5, + T_DIVIDE => 5, + T_PLUS => 5, + T_MINUS => 5, + T_MODULUS => 5, + T_POW => 5, + T_SPACESHIP => 5, + T_COALESCE => 5, + T_COALESCE_EQUAL => 5, + + T_SL => 5, + T_SR => 5, + T_SL_EQUAL => 5, + T_SR_EQUAL => 5, + + T_EQUAL => 5, + T_AND_EQUAL => 5, + T_CONCAT_EQUAL => 5, + T_DIV_EQUAL => 5, + T_MINUS_EQUAL => 5, + T_MOD_EQUAL => 5, + T_MUL_EQUAL => 5, + T_OR_EQUAL => 5, + T_PLUS_EQUAL => 5, + T_XOR_EQUAL => 5, + + T_BOOLEAN_AND => 5, + T_BOOLEAN_OR => 5, + + /* + * Equality. + */ + + T_IS_EQUAL => 5, + T_IS_NOT_EQUAL => 5, + T_IS_IDENTICAL => 5, + T_IS_NOT_IDENTICAL => 5, + T_IS_SMALLER_OR_EQUAL => 5, + T_IS_GREATER_OR_EQUAL => 5, + ]; + + /** + * Tokens that represent assignments. + * + * @var array + */ + public static $assignmentTokens = [ + T_EQUAL => T_EQUAL, + T_AND_EQUAL => T_AND_EQUAL, + T_OR_EQUAL => T_OR_EQUAL, + T_CONCAT_EQUAL => T_CONCAT_EQUAL, + T_DIV_EQUAL => T_DIV_EQUAL, + T_MINUS_EQUAL => T_MINUS_EQUAL, + T_POW_EQUAL => T_POW_EQUAL, + T_MOD_EQUAL => T_MOD_EQUAL, + T_MUL_EQUAL => T_MUL_EQUAL, + T_PLUS_EQUAL => T_PLUS_EQUAL, + T_XOR_EQUAL => T_XOR_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_SL_EQUAL => T_SL_EQUAL, + T_SR_EQUAL => T_SR_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_ZSR_EQUAL => T_ZSR_EQUAL, + ]; + + /** + * Tokens that represent equality comparisons. + * + * @var array + */ + public static $equalityTokens = [ + T_IS_EQUAL => T_IS_EQUAL, + T_IS_NOT_EQUAL => T_IS_NOT_EQUAL, + T_IS_IDENTICAL => T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL, + T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL, + T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL, + ]; + + /** + * Tokens that represent comparison operator. + * + * @var array + */ + public static $comparisonTokens = [ + T_IS_EQUAL => T_IS_EQUAL, + T_IS_IDENTICAL => T_IS_IDENTICAL, + T_IS_NOT_EQUAL => T_IS_NOT_EQUAL, + T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL, + T_LESS_THAN => T_LESS_THAN, + T_GREATER_THAN => T_GREATER_THAN, + T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL, + T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL, + T_SPACESHIP => T_SPACESHIP, + T_COALESCE => T_COALESCE, + ]; + + /** + * Tokens that represent arithmetic operators. + * + * @var array + */ + public static $arithmeticTokens = [ + T_PLUS => T_PLUS, + T_MINUS => T_MINUS, + T_MULTIPLY => T_MULTIPLY, + T_DIVIDE => T_DIVIDE, + T_MODULUS => T_MODULUS, + T_POW => T_POW, + ]; + + /** + * Tokens that perform operations. + * + * @var array + */ + public static $operators = [ + T_MINUS => T_MINUS, + T_PLUS => T_PLUS, + T_MULTIPLY => T_MULTIPLY, + T_DIVIDE => T_DIVIDE, + T_MODULUS => T_MODULUS, + T_POW => T_POW, + T_SPACESHIP => T_SPACESHIP, + T_COALESCE => T_COALESCE, + T_BITWISE_AND => T_BITWISE_AND, + T_BITWISE_OR => T_BITWISE_OR, + T_BITWISE_XOR => T_BITWISE_XOR, + T_SL => T_SL, + T_SR => T_SR, + ]; + + /** + * Tokens that perform boolean operations. + * + * @var array + */ + public static $booleanOperators = [ + T_BOOLEAN_AND => T_BOOLEAN_AND, + T_BOOLEAN_OR => T_BOOLEAN_OR, + T_LOGICAL_AND => T_LOGICAL_AND, + T_LOGICAL_OR => T_LOGICAL_OR, + T_LOGICAL_XOR => T_LOGICAL_XOR, + ]; + + /** + * Tokens that represent casting. + * + * @var array + */ + public static $castTokens = [ + T_INT_CAST => T_INT_CAST, + T_STRING_CAST => T_STRING_CAST, + T_DOUBLE_CAST => T_DOUBLE_CAST, + T_ARRAY_CAST => T_ARRAY_CAST, + T_BOOL_CAST => T_BOOL_CAST, + T_OBJECT_CAST => T_OBJECT_CAST, + T_UNSET_CAST => T_UNSET_CAST, + T_BINARY_CAST => T_BINARY_CAST, + ]; + + /** + * Token types that open parenthesis. + * + * @var array + */ + public static $parenthesisOpeners = [ + T_ARRAY => T_ARRAY, + T_LIST => T_LIST, + T_FUNCTION => T_FUNCTION, + T_CLOSURE => T_CLOSURE, + T_ANON_CLASS => T_ANON_CLASS, + T_WHILE => T_WHILE, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_SWITCH => T_SWITCH, + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + T_CATCH => T_CATCH, + T_DECLARE => T_DECLARE, + T_MATCH => T_MATCH, + ]; + + /** + * Tokens that are allowed to open scopes. + * + * @var array + */ + public static $scopeOpeners = [ + T_CLASS => T_CLASS, + T_ANON_CLASS => T_ANON_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + T_NAMESPACE => T_NAMESPACE, + T_FUNCTION => T_FUNCTION, + T_CLOSURE => T_CLOSURE, + T_IF => T_IF, + T_SWITCH => T_SWITCH, + T_CASE => T_CASE, + T_DECLARE => T_DECLARE, + T_DEFAULT => T_DEFAULT, + T_WHILE => T_WHILE, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_DO => T_DO, + T_TRY => T_TRY, + T_CATCH => T_CATCH, + T_FINALLY => T_FINALLY, + T_PROPERTY => T_PROPERTY, + T_OBJECT => T_OBJECT, + T_USE => T_USE, + T_MATCH => T_MATCH, + ]; + + /** + * Tokens that represent scope modifiers. + * + * @var array + */ + public static $scopeModifiers = [ + T_PRIVATE => T_PRIVATE, + T_PUBLIC => T_PUBLIC, + T_PROTECTED => T_PROTECTED, + ]; + + /** + * Tokens that can prefix a method name + * + * @var array + */ + public static $methodPrefixes = [ + T_PRIVATE => T_PRIVATE, + T_PUBLIC => T_PUBLIC, + T_PROTECTED => T_PROTECTED, + T_ABSTRACT => T_ABSTRACT, + T_STATIC => T_STATIC, + T_FINAL => T_FINAL, + ]; + + /** + * Tokens that open code blocks. + * + * @var array + */ + public static $blockOpeners = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OBJECT => T_OBJECT, + ]; + + /** + * Tokens that don't represent code. + * + * @var array + */ + public static $emptyTokens = [ + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR, + T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG, + T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING, + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that are comments. + * + * @var array + */ + public static $commentTokens = [ + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR, + T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG, + T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING, + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that are comments containing PHPCS instructions. + * + * @var array + */ + public static $phpcsCommentTokens = [ + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that represent strings. + * + * Note that T_STRINGS are NOT represented in this list. + * + * @var array + */ + public static $stringTokens = [ + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + + /** + * Tokens that represent text strings. + * + * @var array + */ + public static $textStringTokens = [ + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + T_INLINE_HTML => T_INLINE_HTML, + T_HEREDOC => T_HEREDOC, + T_NOWDOC => T_NOWDOC, + ]; + + /** + * Tokens that represent brackets and parenthesis. + * + * @var array + */ + public static $bracketTokens = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + ]; + + /** + * Tokens that include files. + * + * @var array + */ + public static $includeTokens = [ + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_REQUIRE => T_REQUIRE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_INCLUDE => T_INCLUDE, + ]; + + /** + * Tokens that make up a heredoc string. + * + * @var array + */ + public static $heredocTokens = [ + T_START_HEREDOC => T_START_HEREDOC, + T_END_HEREDOC => T_END_HEREDOC, + T_HEREDOC => T_HEREDOC, + T_START_NOWDOC => T_START_NOWDOC, + T_END_NOWDOC => T_END_NOWDOC, + T_NOWDOC => T_NOWDOC, + ]; + + /** + * Tokens that represent the names of called functions. + * + * Mostly, these are just strings. But PHP tokenizes some language + * constructs and functions using their own tokens. + * + * @var array + */ + public static $functionNameTokens = [ + T_STRING => T_STRING, + T_EVAL => T_EVAL, + T_EXIT => T_EXIT, + T_INCLUDE => T_INCLUDE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_REQUIRE => T_REQUIRE, + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_ISSET => T_ISSET, + T_UNSET => T_UNSET, + T_EMPTY => T_EMPTY, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + ]; + + /** + * Tokens that open class and object scopes. + * + * @var array + */ + public static $ooScopeTokens = [ + T_CLASS => T_CLASS, + T_ANON_CLASS => T_ANON_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + ]; + + /** + * Tokens representing PHP magic constants. + * + * @var array => + * + * @link https://www.php.net/language.constants.predefined PHP Manual on magic constants + */ + public static $magicConstants = [ + T_CLASS_C => T_CLASS_C, + T_DIR => T_DIR, + T_FILE => T_FILE, + T_FUNC_C => T_FUNC_C, + T_LINE => T_LINE, + T_METHOD_C => T_METHOD_C, + T_NS_C => T_NS_C, + T_TRAIT_C => T_TRAIT_C, + ]; + + /** + * Tokens representing context sensitive keywords in PHP. + * + * @var array + * + * https://wiki.php.net/rfc/context_sensitive_lexer + */ + public static $contextSensitiveKeywords = [ + T_ABSTRACT => T_ABSTRACT, + T_ARRAY => T_ARRAY, + T_AS => T_AS, + T_BREAK => T_BREAK, + T_CALLABLE => T_CALLABLE, + T_CASE => T_CASE, + T_CATCH => T_CATCH, + T_CLASS => T_CLASS, + T_CLONE => T_CLONE, + T_CONST => T_CONST, + T_CONTINUE => T_CONTINUE, + T_DECLARE => T_DECLARE, + T_DEFAULT => T_DEFAULT, + T_DO => T_DO, + T_ECHO => T_ECHO, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_EMPTY => T_EMPTY, + T_ENDDECLARE => T_ENDDECLARE, + T_ENDFOR => T_ENDFOR, + T_ENDFOREACH => T_ENDFOREACH, + T_ENDIF => T_ENDIF, + T_ENDSWITCH => T_ENDSWITCH, + T_ENDWHILE => T_ENDWHILE, + T_ENUM => T_ENUM, + T_EVAL => T_EVAL, + T_EXIT => T_EXIT, + T_EXTENDS => T_EXTENDS, + T_FINAL => T_FINAL, + T_FINALLY => T_FINALLY, + T_FN => T_FN, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_FUNCTION => T_FUNCTION, + T_GLOBAL => T_GLOBAL, + T_GOTO => T_GOTO, + T_IF => T_IF, + T_IMPLEMENTS => T_IMPLEMENTS, + T_INCLUDE => T_INCLUDE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_INSTANCEOF => T_INSTANCEOF, + T_INSTEADOF => T_INSTEADOF, + T_INTERFACE => T_INTERFACE, + T_ISSET => T_ISSET, + T_LIST => T_LIST, + T_LOGICAL_AND => T_LOGICAL_AND, + T_LOGICAL_OR => T_LOGICAL_OR, + T_LOGICAL_XOR => T_LOGICAL_XOR, + T_MATCH => T_MATCH, + T_NAMESPACE => T_NAMESPACE, + T_NEW => T_NEW, + T_PRINT => T_PRINT, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_PUBLIC => T_PUBLIC, + T_READONLY => T_READONLY, + T_REQUIRE => T_REQUIRE, + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_RETURN => T_RETURN, + T_STATIC => T_STATIC, + T_SWITCH => T_SWITCH, + T_THROW => T_THROW, + T_TRAIT => T_TRAIT, + T_TRY => T_TRY, + T_UNSET => T_UNSET, + T_USE => T_USE, + T_VAR => T_VAR, + T_WHILE => T_WHILE, + T_YIELD => T_YIELD, + T_YIELD_FROM => T_YIELD_FROM, + ]; + + + /** + * Given a token, returns the name of the token. + * + * If passed an integer, the token name is sourced from PHP's token_name() + * function. If passed a string, it is assumed to be a PHPCS-supplied token + * that begins with PHPCS_T_, so the name is sourced from the token value itself. + * + * @param int|string $token The token to get the name for. + * + * @return string + */ + public static function tokenName($token) + { + if (is_string($token) === false) { + // PHP-supplied token name. + return token_name($token); + } + + return substr($token, 6); + + }//end tokenName() + + + /** + * Returns the highest weighted token type. + * + * Tokens are weighted by their approximate frequency of appearance in code + * - the less frequently they appear in the code, the higher the weighting. + * For example T_CLASS tokens appear very infrequently in a file, and + * therefore have a high weighting. + * + * Returns false if there are no weightings for any of the specified tokens. + * + * @param array $tokens The token types to get the highest weighted + * type for. + * + * @return int|false The highest weighted token. + */ + public static function getHighestWeightedToken(array $tokens) + { + $highest = -1; + $highestType = false; + + $weights = self::$weightings; + + foreach ($tokens as $token) { + if (isset($weights[$token]) === true) { + $weight = $weights[$token]; + } else { + $weight = 0; + } + + if ($weight > $highest) { + $highest = $weight; + $highestType = $token; + } + } + + return $highestType; + + }//end getHighestWeightedToken() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/AllTests.php b/kirki-composer/squizlabs/php_codesniffer/tests/AllTests.php new file mode 100644 index 000000000..9d099c1e3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/AllTests.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === false) { + include_once 'Core/AllTests.php'; + include_once 'Standards/AllSniffs.php'; +} else { + include_once 'CodeSniffer/Core/AllTests.php'; + include_once 'CodeSniffer/Standards/AllSniffs.php'; + include_once 'FileList.php'; +} + +// PHPUnit 7 made the TestSuite run() method incompatible with +// older PHPUnit versions due to return type hints, so maintain +// two different suite objects. +$phpunit7 = false; +if (class_exists('\PHPUnit\Runner\Version') === true) { + $version = \PHPUnit\Runner\Version::id(); + if ($version[0] === '7') { + $phpunit7 = true; + } +} + +if ($phpunit7 === true) { + include_once 'TestSuite7.php'; +} else { + include_once 'TestSuite.php'; +} + +class PHP_CodeSniffer_AllTests +{ + + + /** + * Add all PHP_CodeSniffer test suites into a single test suite. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'] = []; + $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'] = []; + + // Use a special PHP_CodeSniffer test suite so that we can + // unset our autoload function after the run. + $suite = new TestSuite('PHP CodeSniffer'); + + $suite->addTest(Core\AllTests::suite()); + $suite->addTest(Standards\AllSniffs::suite()); + + return $suite; + + }//end suite() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php new file mode 100644 index 000000000..4d4f54699 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php @@ -0,0 +1,140 @@ + + * @copyright 2018-2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\DummyFile; +use PHPUnit\Framework\TestCase; + +abstract class AbstractMethodUnitTest extends TestCase +{ + + /** + * The file extension of the test case file (without leading dot). + * + * This allows child classes to overrule the default `inc` with, for instance, + * `js` or `css` when applicable. + * + * @var string + */ + protected static $fileExtension = 'inc'; + + /** + * The \PHP_CodeSniffer\Files\File object containing the parsed contents of the test case file. + * + * @var \PHP_CodeSniffer\Files\File + */ + protected static $phpcsFile; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @return void + */ + public static function setUpBeforeClass() + { + $config = new Config(); + $config->standards = ['PSR1']; + + $ruleset = new Ruleset($config); + + // Default to a file with the same name as the test class. Extension is property based. + $relativeCN = str_replace(__NAMESPACE__, '', get_called_class()); + $relativePath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeCN); + $pathToTestFile = realpath(__DIR__).$relativePath.'.'.static::$fileExtension; + + // Make sure the file gets parsed correctly based on the file type. + $contents = 'phpcs_input_file: '.$pathToTestFile.PHP_EOL; + $contents .= file_get_contents($pathToTestFile); + + self::$phpcsFile = new DummyFile($contents, $ruleset, $config); + self::$phpcsFile->process(); + + }//end setUpBeforeClass() + + + /** + * Clean up after finished test. + * + * @return void + */ + public static function tearDownAfterClass() + { + self::$phpcsFile = null; + + }//end tearDownAfterClass() + + + /** + * Get the token pointer for a target token based on a specific comment found on the line before. + * + * Note: the test delimiter comment MUST start with "/* test" to allow this function to + * distinguish between comments used *in* a test and test delimiters. + * + * @param string $commentString The delimiter comment to look for. + * @param int|string|array $tokenType The type of token(s) to look for. + * @param string $tokenContent Optional. The token content for the target token. + * + * @return int + */ + public function getTargetToken($commentString, $tokenType, $tokenContent=null) + { + $start = (self::$phpcsFile->numTokens - 1); + $comment = self::$phpcsFile->findPrevious( + T_COMMENT, + $start, + null, + false, + $commentString + ); + + $tokens = self::$phpcsFile->getTokens(); + $end = ($start + 1); + + // Limit the token finding to between this and the next delimiter comment. + for ($i = ($comment + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] !== T_COMMENT) { + continue; + } + + if (stripos($tokens[$i]['content'], '/* test') === 0) { + $end = $i; + break; + } + } + + $target = self::$phpcsFile->findNext( + $tokenType, + ($comment + 1), + $end, + false, + $tokenContent + ); + + if ($target === false) { + $msg = 'Failed to find test target token for comment string: '.$commentString; + if ($tokenContent !== null) { + $msg .= ' With token content: '.$tokenContent; + } + + $this->assertFalse(true, $msg); + } + + return $target; + + }//end getTargetToken() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/AllTests.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/AllTests.php new file mode 100644 index 000000000..304690eff --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/AllTests.php @@ -0,0 +1,63 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Tests\FileList; +use PHPUnit\TextUI\TestRunner; +use PHPUnit\Framework\TestSuite; + +class AllTests +{ + + + /** + * Prepare the test runner. + * + * @return void + */ + public static function main() + { + TestRunner::run(self::suite()); + + }//end main() + + + /** + * Add all core unit tests into a test suite. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $suite = new TestSuite('PHP CodeSniffer Core'); + + $testFileIterator = new FileList(__DIR__, '', '`Test\.php$`Di'); + foreach ($testFileIterator->fileIterator as $file) { + if (strpos($file, 'AbstractMethodUnitTest.php') !== false) { + continue; + } + + include_once $file; + + $class = str_replace(__DIR__, '', $file); + $class = str_replace('.php', '', $class); + $class = str_replace('/', '\\', $class); + $class = 'PHP_CodeSniffer\Tests\Core'.$class; + + $suite->addTestSuite($class); + } + + return $suite; + + }//end suite() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php new file mode 100644 index 000000000..65542b670 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php @@ -0,0 +1,118 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Autoloader; + +use PHPUnit\Framework\TestCase; + +class DetermineLoadedClassTest extends TestCase +{ + + + /** + * Load the test files. + * + * @return void + */ + public static function setUpBeforeClass() + { + include __DIR__.'/TestFiles/Sub/C.inc'; + + }//end setUpBeforeClass() + + + /** + * Test for when class list is ordered. + * + * @return void + */ + public function testOrdered() + { + $classesBeforeLoad = [ + 'classes' => [], + 'interfaces' => [], + 'traits' => [], + ]; + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + }//end testOrdered() + + + /** + * Test for when class list is out of order. + * + * @return void + */ + public function testUnordered() + { + $classesBeforeLoad = [ + 'classes' => [], + 'interfaces' => [], + 'traits' => [], + ]; + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = \PHP_CodeSniffer\Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + }//end testUnordered() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc new file mode 100644 index 000000000..c1433718b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\DummyFile; +use PHPUnit\Framework\TestCase; + +class ErrorSuppressionTest extends TestCase +{ + + + /** + * Test suppressing a single error. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * + * @dataProvider dataSuppressError + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressError($before, $after, $expectedErrors=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressError() + + + /** + * Data provider. + * + * @see testSuppressError() + * + * @return array + */ + public function dataSuppressError() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Inline slash comments. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable'.PHP_EOL, + 'after' => '// phpcs:enable', + ], + 'disable/enable: multi-line slash comment, tab indented' => [ + 'before' => "\t".'// For reasons'.PHP_EOL."\t".'// phpcs:disable'.PHP_EOL."\t", + 'after' => "\t".'// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable'.PHP_EOL, + 'after' => '// @phpcs:enable', + ], + 'disable/enable: slash comment, mixed case' => [ + 'before' => '// PHPCS:Disable'.PHP_EOL, + 'after' => '// pHPcs:enabLE', + ], + + // Inline hash comments. + 'disable/enable: hash comment' => [ + 'before' => '# phpcs:disable'.PHP_EOL, + 'after' => '# phpcs:enable', + ], + 'disable/enable: multi-line hash comment, tab indented' => [ + 'before' => "\t".'# For reasons'.PHP_EOL."\t".'# phpcs:disable'.PHP_EOL."\t", + 'after' => "\t".'# phpcs:enable', + ], + 'disable/enable: hash comment, with @' => [ + 'before' => '# @phpcs:disable'.PHP_EOL, + 'after' => '# @phpcs:enable', + ], + 'disable/enable: hash comment, mixed case' => [ + 'before' => '# PHPCS:Disable'.PHP_EOL, + 'after' => '# pHPcs:enabLE', + ], + + // Inline star (block) comments. + 'disable/enable: star comment' => [ + 'before' => '/* phpcs:disable */'.PHP_EOL, + 'after' => '/* phpcs:enable */', + ], + 'disable/enable: multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' phpcs:disable'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' phpcs:enable'.PHP_EOL.' */', + ], + 'disable/enable: multi-line star comment, each line starred' => [ + 'before' => '/*'.PHP_EOL.' * phpcs:disable'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' * phpcs:enable'.PHP_EOL.' */', + ], + 'disable/enable: multi-line star comment, each line starred, tab indented' => [ + 'before' => "\t".'/*'.PHP_EOL."\t".' * phpcs:disable'.PHP_EOL."\t".' */'.PHP_EOL."\t", + 'after' => "\t".'/*'.PHP_EOL.' * phpcs:enable'.PHP_EOL.' */', + ], + + // Docblock comments. + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */'.PHP_EOL, + 'after' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart'.PHP_EOL, + 'after' => '// @codingStandardsIgnoreEnd', + ], + 'old style: star comment' => [ + 'before' => '/* @codingStandardsIgnoreStart */'.PHP_EOL, + 'after' => '/* @codingStandardsIgnoreEnd */', + ], + 'old style: multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' @codingStandardsIgnoreStart'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' @codingStandardsIgnoreEnd'.PHP_EOL.' */', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */'.PHP_EOL, + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressError() + + + /** + * Test suppressing 1 out of 2 errors. + * + * @param string $before Annotation to place before the code. + * @param string $between Annotation to place between the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 1. + * + * @dataProvider dataSuppressSomeErrors + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressSomeErrors($before, $between, $expectedErrors=1) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressSomeErrors() + + + /** + * Data provider. + * + * @see testSuppressSomeErrors() + * + * @return array + */ + public function dataSuppressSomeErrors() + { + return [ + 'no suppression' => [ + 'before' => '', + 'between' => '', + 'expectedErrors' => 2, + ], + + // With suppression. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable', + 'between' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable', + 'between' => '// @phpcs:enable', + ], + 'disable/enable: hash comment' => [ + 'before' => '# phpcs:disable', + 'between' => '# phpcs:enable', + ], + 'disable/enable: hash comment, with @' => [ + 'before' => '# @phpcs:disable', + 'between' => '# @phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'between' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'between' => '// @codingStandardsIgnoreEnd', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'between' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressSomeErrors() + + + /** + * Test suppressing a single warning. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataSuppressWarning + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressWarning($before, $after, $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Commenting.Todo']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testSuppressWarning() + + + /** + * Data provider. + * + * @see testSuppressWarning() + * + * @return array + */ + public function dataSuppressWarning() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedWarnings' => 1, + ], + + // With suppression. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'after' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'after' => '// @codingStandardsIgnoreEnd', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressWarning() + + + /** + * Test suppressing a single error using a single line ignore. + * + * @param string $before Annotation to place before the code. + * @param string $after Optional. Annotation to place after the code. + * Defaults to an empty string. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 1. + * + * @dataProvider dataSuppressLine + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressLine($before, $after='', $expectedErrors=1) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressLine() + + + /** + * Data provider. + * + * @see testSuppressLine() + * + * @return array + */ + public function dataSuppressLine() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 2, + ], + + // With suppression on line before. + 'ignore: line before, slash comment' => ['before' => '// phpcs:ignore'], + 'ignore: line before, slash comment, with @' => ['before' => '// @phpcs:ignore'], + 'ignore: line before, hash comment' => ['before' => '# phpcs:ignore'], + 'ignore: line before, hash comment, with @' => ['before' => '# @phpcs:ignore'], + 'ignore: line before, star comment' => ['before' => '/* phpcs:ignore */'], + 'ignore: line before, star comment, with @' => ['before' => '/* @phpcs:ignore */'], + + // With suppression as trailing comment on code line. + 'ignore: end of line, slash comment' => [ + 'before' => '', + 'after' => ' // phpcs:ignore', + ], + 'ignore: end of line, slash comment, with @' => [ + 'before' => '', + 'after' => ' // @phpcs:ignore', + ], + 'ignore: end of line, hash comment' => [ + 'before' => '', + 'after' => ' # phpcs:ignore', + ], + 'ignore: end of line, hash comment, with @' => [ + 'before' => '', + 'after' => ' # @phpcs:ignore', + ], + + // Deprecated syntax. + 'old style: line before, slash comment' => ['before' => '// @codingStandardsIgnoreLine'], + 'old style: end of line, slash comment' => [ + 'before' => '', + 'after' => ' // @codingStandardsIgnoreLine', + ], + ]; + + }//end dataSuppressLine() + + + /** + * Test suppressing a single error using a single line ignore in the middle of a line. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressLineMidLine() + { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + + $content = 'process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testSuppressLineMidLine() + + + /** + * Test suppressing a single error using a single line ignore within a docblock. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressLineWithinDocblock() + { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Files.LineLength']; + + $ruleset = new Ruleset($config); + + // Process with @ suppression on line before inside docblock. + $comment = str_repeat('a ', 50); + $content = <<process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testSuppressLineWithinDocblock() + + + /** + * Test that using a single line ignore does not interfere with other suppressions. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * + * @dataProvider dataNestedSuppressLine + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testNestedSuppressLine($before, $after) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testNestedSuppressLine() + + + /** + * Data provider. + * + * @see testNestedSuppressLine() + * + * @return array + */ + public function dataNestedSuppressLine() + { + return [ + // Process with disable/enable suppression and no single line suppression. + 'disable/enable: slash comment, no single line suppression' => [ + 'before' => '// phpcs:disable', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @, no single line suppression' => [ + 'before' => '// @phpcs:disable', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: hash comment, no single line suppression' => [ + 'before' => '# phpcs:disable', + 'after' => '# phpcs:enable', + ], + 'old style: slash comment, no single line suppression' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'after' => '// @codingStandardsIgnoreEnd', + ], + + // Process with line suppression nested within disable/enable suppression. + 'disable/enable: slash comment, next line nested single line suppression' => [ + 'before' => '// phpcs:disable'.PHP_EOL.'// phpcs:ignore', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @, next line nested single line suppression' => [ + 'before' => '// @phpcs:disable'.PHP_EOL.'// @phpcs:ignore', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: hash comment, next line nested single line suppression' => [ + 'before' => '# @phpcs:disable'.PHP_EOL.'# @phpcs:ignore', + 'after' => '# @phpcs:enable', + ], + 'old style: slash comment, next line nested single line suppression' => [ + 'before' => '// @codingStandardsIgnoreStart'.PHP_EOL.'// @codingStandardsIgnoreLine', + 'after' => '// @codingStandardsIgnoreEnd', + ], + ]; + + }//end dataNestedSuppressLine() + + + /** + * Test suppressing a scope opener. + * + * @param string $before Annotation to place before the scope opener. + * @param string $after Annotation to place after the scope opener. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * + * @dataProvider dataSuppressScope + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressScope($before, $after, $expectedErrors=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['PEAR']; + $config->sniffs = ['PEAR.Functions.FunctionDeclaration']; + + $ruleset = new Ruleset($config); + } + + $content = 'foo(); + } +} +EOD; + $file = new DummyFile($content, $ruleset, $config); + $file->process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressScope() + + + /** + * Data provider. + * + * @see testSuppressScope() + * + * @return array + */ + public function dataSuppressScope() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Process with suppression. + 'disable/enable: slash comment' => [ + 'before' => '//phpcs:disable', + 'after' => '//phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '//@phpcs:disable', + 'after' => '//@phpcs:enable', + ], + 'disable/enable: hash comment' => [ + 'before' => '#phpcs:disable', + 'after' => '#phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'after' => '/** phpcs:enable */', + ], + 'disable/enable: single line docblock comment, with @' => [ + 'before' => '/** @phpcs:disable */', + 'after' => '/** @phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: start/end, slash comment' => [ + 'before' => '//@codingStandardsIgnoreStart', + 'after' => '//@codingStandardsIgnoreEnd', + ], + 'old style: start/end, single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressScope() + + + /** + * Test suppressing a whole file. + * + * @param string $before Annotation to place before the code. + * @param string $after Optional. Annotation to place after the code. + * Defaults to an empty string. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataSuppressFile + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testSuppressFile($before, $after='', $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Commenting.Todo']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testSuppressFile() + + + /** + * Data provider. + * + * @see testSuppressFile() + * + * @return array + */ + public function dataSuppressFile() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Process with suppression. + 'ignoreFile: start of file, slash comment' => ['before' => '// phpcs:ignoreFile'], + 'ignoreFile: start of file, slash comment, with @' => ['before' => '// @phpcs:ignoreFile'], + 'ignoreFile: start of file, slash comment, mixed case' => ['before' => '// PHPCS:Ignorefile'], + 'ignoreFile: start of file, hash comment' => ['before' => '# phpcs:ignoreFile'], + 'ignoreFile: start of file, hash comment, with @' => ['before' => '# @phpcs:ignoreFile'], + 'ignoreFile: start of file, single-line star comment' => ['before' => '/* phpcs:ignoreFile */'], + 'ignoreFile: start of file, multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' phpcs:ignoreFile'.PHP_EOL.' */', + ], + 'ignoreFile: start of file, single-line docblock comment' => ['before' => '/** phpcs:ignoreFile */'], + + // Process late comment. + 'ignoreFile: late comment, slash comment' => [ + 'before' => '', + 'after' => '// phpcs:ignoreFile', + ], + + // Deprecated syntax. + 'old style: start of file, slash comment' => ['before' => '// @codingStandardsIgnoreFile'], + 'old style: start of file, single-line star comment' => ['before' => '/* @codingStandardsIgnoreFile */'], + 'old style: start of file, multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' @codingStandardsIgnoreFile'.PHP_EOL.' */', + ], + 'old style: start of file, single-line docblock comment' => ['before' => '/** @codingStandardsIgnoreFile */'], + + // Deprecated syntax, late comment. + 'old style: late comment, slash comment' => [ + 'before' => '', + 'after' => '// @codingStandardsIgnoreFile', + ], + ]; + + }//end dataSuppressFile() + + + /** + * Test disabling specific sniffs. + * + * @param string $before Annotation to place before the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataDisableSelected + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testDisableSelected($before, $expectedErrors=0, $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testDisableSelected() + + + /** + * Data provider. + * + * @see testDisableSelected() + * + * @return array + */ + public function dataDisableSelected() + { + return [ + // Single sniff. + 'disable: single sniff' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo', + 'expectedErrors' => 1, + ], + 'disable: single sniff with reason' => [ + 'before' => '# phpcs:disable Generic.Commenting.Todo -- for reasons', + 'expectedErrors' => 1, + ], + 'disable: single sniff, docblock' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + ], + 'disable: single sniff, docblock, with @' => [ + 'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + ], + + // Multiple sniffs. + 'disable: multiple sniffs in one comment' => ['before' => '// phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant'], + 'disable: multiple sniff in multiple comments' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:disable Generic.PHP.LowerCaseConstant', + ], + + // Selectiveness variations. + 'disable: complete category' => [ + 'before' => '// phpcs:disable Generic.Commenting', + 'expectedErrors' => 1, + ], + 'disable: whole standard' => ['before' => '// phpcs:disable Generic'], + 'disable: single errorcode' => [ + 'before' => '# @phpcs:disable Generic.Commenting.Todo.TaskFound', + 'expectedErrors' => 1, + ], + 'disable: single errorcode and a category' => ['before' => '// phpcs:disable Generic.PHP.LowerCaseConstant.Found,Generic.Commenting'], + + // Wrong category/sniff/code. + 'disable: wrong error code and category' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.PHP.LowerCaseConstant.Upper,Generic.Comments'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: wrong category, docblock' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Files'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: wrong category, docblock, with @' => [ + 'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Files'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + ]; + + }//end dataDisableSelected() + + + /** + * Test re-enabling specific sniffs that have been disabled. + * + * @param string $code Code pattern to check. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataEnableSelected + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testEnableSelected($code, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testEnableSelected() + + + /** + * Data provider. + * + * @see testEnableSelected() + * + * @return array + */ + public function dataEnableSelected() + { + return [ + 'disable/enable: a single sniff' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable/enable: multiple sniffs' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: multiple sniffs; enable: one' => [ + 'code' => ' + # phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + # phpcs:enable Generic.Commenting.Todo + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable/enable: complete category' => [ + 'code' => ' + // phpcs:disable Generic.Commenting + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable/enable: whole standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: category from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: a category; enable: the whole standard containing the category' => [ + 'code' => ' + # phpcs:disable Generic.Commenting + $var = FALSE; + //TODO: write some code + # phpcs:enable Generic + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; enable: the category containing the sniff' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: single sniff from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: single sniff from the standard; disable: that same sniff; enable: everything' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code + // phpcs:disable Generic.Commenting.Todo + //TODO: write some code + // phpcs:enable + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 2, + ], + 'disable: whole standard; enable: single sniff from the standard; enable: other sniff from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code + $var = FALSE; + // phpcs:enable Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 2, + ], + ]; + + }//end dataEnableSelected() + + + /** + * Test ignoring specific sniffs. + * + * @param string $before Annotation to place before the code. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataIgnoreSelected + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testIgnoreSelected($before, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testIgnoreSelected() + + + /** + * Data provider. + * + * @see testIgnoreSelected() + * + * @return array + */ + public function dataIgnoreSelected() + { + return [ + 'no suppression' => [ + 'before' => '', + 'expectedErrors' => 2, + 'expectedWarnings' => 2, + ], + + // With suppression. + 'ignore: single sniff' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'ignore: multiple sniffs' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; ignore: single sniff' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:ignore Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 0, + ], + 'ignore: category of sniffs' => [ + 'before' => '# phpcs:ignore Generic.Commenting', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'ignore: whole standard' => [ + 'before' => '// phpcs:ignore Generic', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + ]; + + }//end dataIgnoreSelected() + + + /** + * Test ignoring specific sniffs. + * + * @param string $code Code pattern to check. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataCommenting + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + * + * @return void + */ + public function testCommenting($code, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new Config(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testCommenting() + + + /** + * Data provider. + * + * @see testCommenting() + * + * @return array + */ + public function dataCommenting() + { + return [ + 'ignore: single sniff' => [ + 'code' => ' + // phpcs:ignore Generic.Commenting.Todo -- Because reasons + $var = FALSE; //TODO: write some code + $var = FALSE; //TODO: write some code', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; enable: same sniff - test whitespace handling around reason delimiter' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo --Because reasons + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo -- Because reasons + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff, multi-line comment' => [ + 'code' => ' + /* + Disable some checks + phpcs:disable Generic.Commenting.Todo + */ + $var = FALSE; + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 0, + ], + 'ignore: single sniff, multi-line slash comment' => [ + 'code' => ' + // Turn off a check for the next line of code. + // phpcs:ignore Generic.Commenting.Todo + $var = FALSE; //TODO: write some code + $var = FALSE; //TODO: write some code', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'enable before disable, sniff not in standard' => [ + 'code' => ' + // phpcs:enable Generic.PHP.NoSilencedErrors -- Because reasons + $var = @delete( $filename ); + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], + ]; + + }//end dataCommenting() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc new file mode 100644 index 000000000..6dfd0a280 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc @@ -0,0 +1,105 @@ + fn() => return 1, + 'b' => fn() => return 1, +]; + +/* testStaticArrowFunction */ +static fn ($a) => $a; + +/* testArrowFunctionReturnValue */ +fn(): array => [a($a, $b)]; + +/* testArrowFunctionAsArgument */ +$foo = foo( + fn() => bar() +); + +/* testArrowFunctionWithArrayAsArgument */ +$foo = foo( + fn() => [$row[0], $row[3]] +); + +$match = match ($a) { + /* testMatchCase */ + 1 => 'foo', + /* testMatchDefault */ + default => 'bar' +}; + +$match = match ($a) { + /* testMatchMultipleCase */ + 1, 2, => $a * $b, + /* testMatchDefaultComma */ + default, => 'something' +}; + +match ($pressedKey) { + /* testMatchFunctionCall */ + Key::RETURN_ => save($value, $user) +}; + +$result = match (true) { + /* testMatchFunctionCallArm */ + str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', + str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', + default => 'pl' +}; + +/* testMatchClosure */ +$result = match ($key) { + 1 => function($a, $b) {}, + 2 => function($b, $c) {}, +}; + +/* testMatchArray */ +$result = match ($key) { + 1 => [1,2,3], + 2 => [1 => one(), 2 => two()], +}; + +/* testNestedMatch */ +$result = match ($key) { + 1 => match ($key) { + 1 => 'one', + 2 => 'two', + }, + 2 => match ($key) { + 1 => 'two', + 2 => 'one', + }, +}; + +return 0; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php new file mode 100644 index 000000000..7bff26b56 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php @@ -0,0 +1,415 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindEndOfStatementTest extends AbstractMethodUnitTest +{ + + + /** + * Test a simple assignment. + * + * @return void + */ + public function testSimpleAssignment() + { + $start = $this->getTargetToken('/* testSimpleAssignment */', T_VARIABLE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testSimpleAssignment() + + + /** + * Test a direct call to a control structure. + * + * @return void + */ + public function testControlStructure() + { + $start = $this->getTargetToken('/* testControlStructure */', T_WHILE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 6), $found); + + }//end testControlStructure() + + + /** + * Test the assignment of a closure. + * + * @return void + */ + public function testClosureAssignment() + { + $start = $this->getTargetToken('/* testClosureAssignment */', T_VARIABLE, '$a'); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 13), $found); + + }//end testClosureAssignment() + + + /** + * Test using a heredoc in a function argument. + * + * @return void + */ + public function testHeredocFunctionArg() + { + // Find the end of the function. + $start = $this->getTargetToken('/* testHeredocFunctionArg */', T_STRING, 'myFunction'); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 10), $found); + + // Find the end of the heredoc. + $start += 2; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 4), $found); + + // Find the end of the last arg. + $start = ($found + 2); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame($start, $found); + + }//end testHeredocFunctionArg() + + + /** + * Test parts of a switch statement. + * + * @return void + */ + public function testSwitch() + { + // Find the end of the switch. + $start = $this->getTargetToken('/* testSwitch */', T_SWITCH); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 28), $found); + + // Find the end of the case. + $start += 9; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 8), $found); + + // Find the end of default case. + $start += 11; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 6), $found); + + }//end testSwitch() + + + /** + * Test statements that are array values. + * + * @return void + */ + public function testStatementAsArrayValue() + { + // Test short array syntax. + $start = $this->getTargetToken('/* testStatementAsArrayValue */', T_NEW); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 2), $found); + + // Test long array syntax. + $start += 12; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 2), $found); + + // Test same statement outside of array. + $start += 10; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 3), $found); + + }//end testStatementAsArrayValue() + + + /** + * Test a use group. + * + * @return void + */ + public function testUseGroup() + { + $start = $this->getTargetToken('/* testUseGroup */', T_USE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 23), $found); + + }//end testUseGroup() + + + /** + * Test arrow function as array value. + * + * @return void + */ + public function testArrowFunctionArrayValue() + { + $start = $this->getTargetToken('/* testArrowFunctionArrayValue */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 9), $found); + + }//end testArrowFunctionArrayValue() + + + /** + * Test static arrow function. + * + * @return void + */ + public function testStaticArrowFunction() + { + $static = $this->getTargetToken('/* testStaticArrowFunction */', T_STATIC); + $fn = $this->getTargetToken('/* testStaticArrowFunction */', T_FN); + + $endOfStatementStatic = self::$phpcsFile->findEndOfStatement($static); + $endOfStatementFn = self::$phpcsFile->findEndOfStatement($fn); + + $this->assertSame($endOfStatementFn, $endOfStatementStatic); + + }//end testStaticArrowFunction() + + + /** + * Test arrow function with return value. + * + * @return void + */ + public function testArrowFunctionReturnValue() + { + $start = $this->getTargetToken('/* testArrowFunctionReturnValue */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 18), $found); + + }//end testArrowFunctionReturnValue() + + + /** + * Test arrow function used as a function argument. + * + * @return void + */ + public function testArrowFunctionAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionAsArgument */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 8), $found); + + }//end testArrowFunctionAsArgument() + + + /** + * Test arrow function with arrays used as a function argument. + * + * @return void + */ + public function testArrowFunctionWithArrayAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionWithArrayAsArgument */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 17), $found); + + }//end testArrowFunctionWithArrayAsArgument() + + + /** + * Test simple match expression case. + * + * @return void + */ + public function testMatchCase() + { + $start = $this->getTargetToken('/* testMatchCase */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + $start = $this->getTargetToken('/* testMatchCase */', T_CONSTANT_ENCAPSED_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 1), $found); + + }//end testMatchCase() + + + /** + * Test simple match expression default case. + * + * @return void + */ + public function testMatchDefault() + { + $start = $this->getTargetToken('/* testMatchDefault */', T_MATCH_DEFAULT); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 4), $found); + + $start = $this->getTargetToken('/* testMatchDefault */', T_CONSTANT_ENCAPSED_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefault() + + + /** + * Test multiple comma-separated match expression case values. + * + * @return void + */ + public function testMatchMultipleCase() + { + $start = $this->getTargetToken('/* testMatchMultipleCase */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + $this->assertSame(($start + 13), $found); + + $start += 6; + $found = self::$phpcsFile->findEndOfStatement($start); + $this->assertSame(($start + 7), $found); + + }//end testMatchMultipleCase() + + + /** + * Test match expression default case with trailing comma. + * + * @return void + */ + public function testMatchDefaultComma() + { + $start = $this->getTargetToken('/* testMatchDefaultComma */', T_MATCH_DEFAULT); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testMatchDefaultComma() + + + /** + * Test match expression with function call. + * + * @return void + */ + public function testMatchFunctionCall() + { + $start = $this->getTargetToken('/* testMatchFunctionCall */', T_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 12), $found); + + $start += 8; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 1), $found); + + }//end testMatchFunctionCall() + + + /** + * Test match expression with function call in the arm. + * + * @return void + */ + public function testMatchFunctionCallArm() + { + // Check the first case. + $start = $this->getTargetToken('/* testMatchFunctionCallArm */', T_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 21), $found); + + // Check the second case. + $start += 24; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 21), $found); + + }//end testMatchFunctionCallArm() + + + /** + * Test match expression with closure. + * + * @return void + */ + public function testMatchClosure() + { + $start = $this->getTargetToken('/* testMatchClosure */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 14), $found); + + $start += 17; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 14), $found); + + }//end testMatchClosure() + + + /** + * Test match expression with array declaration. + * + * @return void + */ + public function testMatchArray() + { + $start = $this->getTargetToken('/* testMatchArray */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 11), $found); + + $start += 14; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 22), $found); + + }//end testMatchArray() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testNestedMatch() + { + $start = $this->getTargetToken('/* testNestedMatch */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 30), $found); + + $start += 21; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testNestedMatch() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc new file mode 100644 index 000000000..aead06cd9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc @@ -0,0 +1,37 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindExtendedClassNameTest extends AbstractMethodUnitTest +{ + + + /** + * Test retrieving the name of the class being extended by another class + * (or interface). + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataExtendedClass + * + * @return void + */ + public function testFindExtendedClassName($identifier, $expected) + { + $OOToken = $this->getTargetToken($identifier, [T_CLASS, T_ANON_CLASS, T_INTERFACE]); + $result = self::$phpcsFile->findExtendedClassName($OOToken); + $this->assertSame($expected, $result); + + }//end testFindExtendedClassName() + + + /** + * Data provider for the FindExtendedClassName test. + * + * @see testFindExtendedClassName() + * + * @return array + */ + public function dataExtendedClass() + { + return [ + [ + '/* testExtendedClass */', + 'testFECNClass', + ], + [ + '/* testNamespacedClass */', + '\PHP_CodeSniffer\Tests\Core\File\testFECNClass', + ], + [ + '/* testNonExtendedClass */', + false, + ], + [ + '/* testInterface */', + false, + ], + [ + '/* testInterfaceThatExtendsInterface */', + 'testFECNInterface', + ], + [ + '/* testInterfaceThatExtendsFQCNInterface */', + '\PHP_CodeSniffer\Tests\Core\File\testFECNInterface', + ], + [ + '/* testNestedExtendedClass */', + false, + ], + [ + '/* testNestedExtendedAnonClass */', + 'testFECNAnonClass', + ], + [ + '/* testClassThatExtendsAndImplements */', + 'testFECNClass', + ], + [ + '/* testClassThatImplementsAndExtends */', + 'testFECNClass', + ], + ]; + + }//end dataExtendedClass() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc new file mode 100644 index 000000000..44c0f6432 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindImplementedInterfaceNamesTest extends AbstractMethodUnitTest +{ + + + /** + * Test retrieving the name(s) of the interfaces being implemented by a class. + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataImplementedInterface + * + * @return void + */ + public function testFindImplementedInterfaceNames($identifier, $expected) + { + $OOToken = $this->getTargetToken($identifier, [T_CLASS, T_ANON_CLASS, T_INTERFACE, T_ENUM]); + $result = self::$phpcsFile->findImplementedInterfaceNames($OOToken); + $this->assertSame($expected, $result); + + }//end testFindImplementedInterfaceNames() + + + /** + * Data provider for the FindImplementedInterfaceNames test. + * + * @see testFindImplementedInterfaceNames() + * + * @return array + */ + public function dataImplementedInterface() + { + return [ + [ + '/* testImplementedClass */', + ['testFIINInterface'], + ], + [ + '/* testMultiImplementedClass */', + [ + 'testFIINInterface', + 'testFIINInterface2', + ], + ], + [ + '/* testNamespacedClass */', + ['\PHP_CodeSniffer\Tests\Core\File\testFIINInterface'], + ], + [ + '/* testNonImplementedClass */', + false, + ], + [ + '/* testInterface */', + false, + ], + [ + '/* testClassThatExtendsAndImplements */', + [ + 'InterfaceA', + '\NameSpaced\Cat\InterfaceB', + ], + ], + [ + '/* testClassThatImplementsAndExtends */', + [ + '\InterfaceA', + 'InterfaceB', + ], + ], + [ + '/* testBackedEnumWithoutImplements */', + false, + ], + [ + '/* testEnumImplements */', + ['Colorful'], + ], + [ + '/* testBackedEnumImplements */', + [ + 'Colorful', + '\Deck', + ], + ], + ]; + + }//end dataImplementedInterface() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc new file mode 100644 index 000000000..ce9dfad3f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc @@ -0,0 +1,123 @@ + $foo + $bar, 'b' => true]; + +/* testUseGroup */ +use Vendor\Package\{ClassA as A, ClassB, ClassC as C}; + +$a = [ + /* testArrowFunctionArrayValue */ + 'a' => fn() => return 1, + 'b' => fn() => return 1, +]; + +/* testStaticArrowFunction */ +static fn ($a) => $a; + +/* testArrowFunctionReturnValue */ +fn(): array => [a($a, $b)]; + +/* testArrowFunctionAsArgument */ +$foo = foo( + fn() => bar() +); + +/* testArrowFunctionWithArrayAsArgument */ +$foo = foo( + fn() => [$row[0], $row[3]] +); + +$match = match ($a) { + /* testMatchCase */ + 1 => 'foo', + /* testMatchDefault */ + default => 'bar' +}; + +$match = match ($a) { + /* testMatchMultipleCase */ + 1, 2, => $a * $b, + /* testMatchDefaultComma */ + default, => 'something' +}; + +match ($pressedKey) { + /* testMatchFunctionCall */ + Key::RETURN_ => save($value, $user) +}; + +$result = match (true) { + /* testMatchFunctionCallArm */ + str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', + str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', + default => 'pl' +}; + +/* testMatchClosure */ +$result = match ($key) { + 1 => function($a, $b) {}, + 2 => function($b, $c) {}, +}; + +/* testMatchArray */ +$result = match ($key) { + 1 => [1,2,3], + 2 => [1 => one($a, $b), 2 => two($b, $c)], + 3 => [], +}; + +/* testNestedMatch */ +$result = match ($key) { + 1 => match ($key) { + 1 => 'one', + 2 => 'two', + }, + 2 => match ($key) { + 1 => 'two', + 2 => 'one', + }, +}; + +return 0; + +/* testOpenTag */ +?> +

    Test

    +', foo(), ''; + +/* testOpenTagWithEcho */ +?> +

    Test

    +', foo(), ''; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php new file mode 100644 index 000000000..464021f6f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php @@ -0,0 +1,503 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FindStartOfStatementTest extends AbstractMethodUnitTest +{ + + + /** + * Test a simple assignment. + * + * @return void + */ + public function testSimpleAssignment() + { + $start = $this->getTargetToken('/* testSimpleAssignment */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + }//end testSimpleAssignment() + + + /** + * Test a function call. + * + * @return void + */ + public function testFunctionCall() + { + $start = $this->getTargetToken('/* testFunctionCall */', T_CLOSE_PARENTHESIS); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testFunctionCall() + + + /** + * Test a function call. + * + * @return void + */ + public function testFunctionCallArgument() + { + $start = $this->getTargetToken('/* testFunctionCallArgument */', T_VARIABLE, '$b'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testFunctionCallArgument() + + + /** + * Test a direct call to a control structure. + * + * @return void + */ + public function testControlStructure() + { + $start = $this->getTargetToken('/* testControlStructure */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testControlStructure() + + + /** + * Test the assignment of a closure. + * + * @return void + */ + public function testClosureAssignment() + { + $start = $this->getTargetToken('/* testClosureAssignment */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 12), $found); + + }//end testClosureAssignment() + + + /** + * Test using a heredoc in a function argument. + * + * @return void + */ + public function testHeredocFunctionArg() + { + // Find the start of the function. + $start = $this->getTargetToken('/* testHeredocFunctionArg */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + // Find the start of the heredoc. + $start -= 4; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 4), $found); + + // Find the start of the last arg. + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testHeredocFunctionArg() + + + /** + * Test parts of a switch statement. + * + * @return void + */ + public function testSwitch() + { + // Find the start of the switch. + $start = $this->getTargetToken('/* testSwitch */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 47), $found); + + // Find the start of default case. + $start -= 5; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + // Find the start of the second case. + $start -= 12; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + // Find the start of the first case. + $start -= 13; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 8), $found); + + // Test inside the first case. + $start--; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testSwitch() + + + /** + * Test statements that are array values. + * + * @return void + */ + public function testStatementAsArrayValue() + { + // Test short array syntax. + $start = $this->getTargetToken('/* testStatementAsArrayValue */', T_STRING, 'Datetime'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + // Test long array syntax. + $start += 12; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + // Test same statement outside of array. + $start++; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 9), $found); + + // Test with an array index. + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + }//end testStatementAsArrayValue() + + + /** + * Test a use group. + * + * @return void + */ + public function testUseGroup() + { + $start = $this->getTargetToken('/* testUseGroup */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 23), $found); + + }//end testUseGroup() + + + /** + * Test arrow function as array value. + * + * @return void + */ + public function testArrowFunctionArrayValue() + { + $start = $this->getTargetToken('/* testArrowFunctionArrayValue */', T_COMMA); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 9), $found); + + }//end testArrowFunctionArrayValue() + + + /** + * Test static arrow function. + * + * @return void + */ + public function testStaticArrowFunction() + { + $start = $this->getTargetToken('/* testStaticArrowFunction */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 11), $found); + + }//end testStaticArrowFunction() + + + /** + * Test arrow function with return value. + * + * @return void + */ + public function testArrowFunctionReturnValue() + { + $start = $this->getTargetToken('/* testArrowFunctionReturnValue */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + }//end testArrowFunctionReturnValue() + + + /** + * Test arrow function used as a function argument. + * + * @return void + */ + public function testArrowFunctionAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionAsArgument */', T_FN); + $start += 8; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 8), $found); + + }//end testArrowFunctionAsArgument() + + + /** + * Test arrow function with arrays used as a function argument. + * + * @return void + */ + public function testArrowFunctionWithArrayAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionWithArrayAsArgument */', T_FN); + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 17), $found); + + }//end testArrowFunctionWithArrayAsArgument() + + + /** + * Test simple match expression case. + * + * @return void + */ + public function testMatchCase() + { + $start = $this->getTargetToken('/* testMatchCase */', T_COMMA); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testMatchCase() + + + /** + * Test simple match expression default case. + * + * @return void + */ + public function testMatchDefault() + { + $start = $this->getTargetToken('/* testMatchDefault */', T_CONSTANT_ENCAPSED_STRING, "'bar'"); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefault() + + + /** + * Test multiple comma-separated match expression case values. + * + * @return void + */ + public function testMatchMultipleCase() + { + $start = $this->getTargetToken('/* testMatchMultipleCase */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + $start += 6; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 4), $found); + + }//end testMatchMultipleCase() + + + /** + * Test match expression default case with trailing comma. + * + * @return void + */ + public function testMatchDefaultComma() + { + $start = $this->getTargetToken('/* testMatchDefaultComma */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 3), $found); + + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefaultComma() + + + /** + * Test match expression with function call. + * + * @return void + */ + public function testMatchFunctionCall() + { + $start = $this->getTargetToken('/* testMatchFunctionCall */', T_CLOSE_PARENTHESIS); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testMatchFunctionCall() + + + /** + * Test match expression with function call in the arm. + * + * @return void + */ + public function testMatchFunctionCallArm() + { + // Check the first case. + $start = $this->getTargetToken('/* testMatchFunctionCallArm */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + // Check the second case. + $start += 24; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + }//end testMatchFunctionCallArm() + + + /** + * Test match expression with closure. + * + * @return void + */ + public function testMatchClosure() + { + $start = $this->getTargetToken('/* testMatchClosure */', T_LNUMBER); + $start += 14; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + }//end testMatchClosure() + + + /** + * Test match expression with array declaration. + * + * @return void + */ + public function testMatchArray() + { + // Start of first case statement. + $start = $this->getTargetToken('/* testMatchArray */', T_LNUMBER); + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame($start, $found); + + // Comma after first statement. + $start += 11; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame(($start - 7), $found); + + // Start of second case statement. + $start += 3; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame($start, $found); + + // Comma after first statement. + $start += 30; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame(($start - 26), $found); + + }//end testMatchArray() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testNestedMatch() + { + $start = $this->getTargetToken('/* testNestedMatch */', T_LNUMBER); + $start += 30; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 26), $found); + + $start -= 4; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + $start -= 3; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + }//end testNestedMatch() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testOpenTag() + { + $start = $this->getTargetToken('/* testOpenTag */', T_OPEN_TAG); + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testOpenTag() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testOpenTagWithEcho() + { + $start = $this->getTargetToken('/* testOpenTagWithEcho */', T_OPEN_TAG_WITH_ECHO); + $start += 3; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testOpenTagWithEcho() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc new file mode 100644 index 000000000..f40b6021f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc @@ -0,0 +1,304 @@ + 'a', 'b' => 'b' ), + /* testGroupPrivate 3 */ + $varQ = 'string', + /* testGroupPrivate 4 */ + $varR = 123, + /* testGroupPrivate 5 */ + $varS = ONE / self::THREE, + /* testGroupPrivate 6 */ + $varT = [ + 'a' => 'a', + 'b' => 'b' + ], + /* testGroupPrivate 7 */ + $varU = __DIR__ . "/base"; + + + /* testMethodParam */ + public function methodName($param) { + /* testImportedGlobal */ + global $importedGlobal = true; + + /* testLocalVariable */ + $localVariable = true; + } + + /* testPropertyAfterMethod */ + private static $varV = true; + + /* testMessyNullableType */ + public /* comment + */ ? //comment + array $foo = []; + + /* testNamespaceType */ + public \MyNamespace\MyClass $foo; + + /* testNullableNamespaceType 1 */ + private ?ClassName $nullableClassType; + + /* testNullableNamespaceType 2 */ + protected ?Folder\ClassName $nullableClassType2; + + /* testMultilineNamespaceType */ + public \MyNamespace /** comment *\/ comment */ + \MyClass /* comment */ + \Foo $foo; + +} + +interface Base +{ + /* testInterfaceProperty */ + protected $anonymous; +} + +/* testGlobalVariable */ +$globalVariable = true; + +/* testNotAVariable */ +return; + +$a = ( $foo == $bar ? new stdClass() : + new class() { + /* testNestedProperty 1 */ + public $var = true; + + /* testNestedMethodParam 1 */ + public function something($var = false) {} + } +); + +function_call( 'param', new class { + /* testNestedProperty 2 */ + public $year = 2017; + + /* testNestedMethodParam 2 */ + public function __construct( $open, $post_id ) {} +}, 10, 2 ); + +class PHP8Mixed { + /* testPHP8MixedTypeHint */ + public static miXed $mixed; + + /* testPHP8MixedTypeHintNullable */ + // Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. + private ?mixed $nullableMixed; +} + +class NSOperatorInType { + /* testNamespaceOperatorTypeHint */ + public ?namespace\Name $prop; +} + +$anon = class() { + /* testPHP8UnionTypesSimple */ + public int|float $unionTypeSimple; + + /* testPHP8UnionTypesTwoClasses */ + private MyClassA|\Package\MyClassB $unionTypesTwoClasses; + + /* testPHP8UnionTypesAllBaseTypes */ + protected array|bool|int|float|NULL|object|string $unionTypesAllBaseTypes; + + /* testPHP8UnionTypesAllPseudoTypes */ + // Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. + var false|mixed|self|parent|iterable|Resource $unionTypesAllPseudoTypes; + + /* testPHP8UnionTypesIllegalTypes */ + // Intentional fatal error - types which are not allowed for properties, but that's not the concern of the method. + public callable|static|void $unionTypesIllegalTypes; + + /* testPHP8UnionTypesNullable */ + // Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. + public ?int|float $unionTypesNullable; + + /* testPHP8PseudoTypeNull */ + // Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. + public null $pseudoTypeNull; + + /* testPHP8PseudoTypeFalse */ + // Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. + public false $pseudoTypeFalse; + + /* testPHP8PseudoTypeFalseAndBool */ + // Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. + public bool|FALSE $pseudoTypeFalseAndBool; + + /* testPHP8ObjectAndClass */ + // Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. + public object|ClassName $objectAndClass; + + /* testPHP8PseudoTypeIterableAndArray */ + // Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. + public iterable|array|Traversable $pseudoTypeIterableAndArray; + + /* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ + // Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. + public int |string| /*comment*/ INT $duplicateTypeInUnion; + + /* testPHP81Readonly */ + public readonly int $readonly; + + /* testPHP81ReadonlyWithNullableType */ + public readonly ?array $array; + + /* testPHP81ReadonlyWithUnionType */ + public readonly string|int $readonlyWithUnionType; + + /* testPHP81ReadonlyWithUnionTypeWithNull */ + protected ReadOnly string|null $readonlyWithUnionTypeWithNull; + + /* testPHP81OnlyReadonlyWithUnionType */ + readonly string|int $onlyReadonly; +}; + +$anon = class { + /* testPHP8PropertySingleAttribute */ + #[PropertyWithAttribute] + public string $foo; + + /* testPHP8PropertyMultipleAttributes */ + #[PropertyWithAttribute(foo: 'bar'), MyAttribute] + protected ?int|float $bar; + + /* testPHP8PropertyMultilineAttribute */ + #[ + PropertyWithAttribute(/* comment */ 'baz') + ] + private mixed $baz; +}; + +enum Suit +{ + /* testEnumProperty */ + protected $anonymous; +} + +enum Direction implements ArrayAccess +{ + case Up; + case Down; + + /* testEnumMethodParamNotProperty */ + public function offsetGet($val) { ... } +} + +$anon = class() { + /* testPHP81IntersectionTypes */ + public Foo&Bar $intersectionType; + + /* testPHP81MoreIntersectionTypes */ + public Foo&Bar&Baz $moreIntersectionTypes; + + /* testPHP81IllegalIntersectionTypes */ + // Intentional fatal error - types which are not allowed for intersection type, but that's not the concern of the method. + public int&string $illegalIntersectionType; + + /* testPHP81NulltableIntersectionType */ + // Intentional fatal error - nullability is not allowed with intersection type, but that's not the concern of the method. + public ?Foo&Bar $nullableIntersectionType; +}; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php new file mode 100644 index 000000000..69dfde1e7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php @@ -0,0 +1,864 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GetMemberPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test the getMemberProperties() method. + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataGetMemberProperties + * + * @return void + */ + public function testGetMemberProperties($identifier, $expected) + { + $variable = $this->getTargetToken($identifier, T_VARIABLE); + $result = self::$phpcsFile->getMemberProperties($variable); + + $this->assertArraySubset($expected, $result, true); + + }//end testGetMemberProperties() + + + /** + * Data provider for the GetMemberProperties test. + * + * @see testGetMemberProperties() + * + * @return array + */ + public function dataGetMemberProperties() + { + return [ + [ + '/* testVar */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testVarType */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int', + 'nullable_type' => true, + ], + ], + [ + '/* testPublic */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPublicType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'string', + 'nullable_type' => false, + ], + ], + [ + '/* testProtected */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testProtectedType */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'bool', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivate */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivateType */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'array', + 'nullable_type' => false, + ], + ], + [ + '/* testStatic */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testStaticType */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'nullable_type' => true, + ], + ], + [ + '/* testStaticVar */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testVarStatic */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPublicStatic */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testProtectedStatic */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivateStatic */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPublicStaticWithDocblock */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testProtectedStaticWithDocblock */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPrivateStaticWithDocblock */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupType 1 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'float', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupType 2 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'float', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupNullableType 1 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'nullable_type' => true, + ], + ], + [ + '/* testGroupNullableType 2 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'nullable_type' => true, + ], + ], + [ + '/* testNoPrefix */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupProtectedStatic 1 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupProtectedStatic 2 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupProtectedStatic 3 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 1 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 2 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 3 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 4 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 5 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 6 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testGroupPrivate 7 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testMessyNullableType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?array', + 'nullable_type' => true, + ], + ], + [ + '/* testNamespaceType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\MyNamespace\MyClass', + 'nullable_type' => false, + ], + ], + [ + '/* testNullableNamespaceType 1 */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?ClassName', + 'nullable_type' => true, + ], + ], + [ + '/* testNullableNamespaceType 2 */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?Folder\ClassName', + 'nullable_type' => true, + ], + ], + [ + '/* testMultilineNamespaceType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\MyNamespace\MyClass\Foo', + 'nullable_type' => false, + ], + ], + [ + '/* testPropertyAfterMethod */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testInterfaceProperty */', + [], + ], + [ + '/* testNestedProperty 1 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testNestedProperty 2 */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8MixedTypeHint */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => 'miXed', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8MixedTypeHintNullable */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?mixed', + 'nullable_type' => true, + ], + ], + [ + '/* testNamespaceOperatorTypeHint */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?namespace\Name', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP8UnionTypesSimple */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|float', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesTwoClasses */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'MyClassA|\Package\MyClassB', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesAllBaseTypes */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'array|bool|int|float|NULL|object|string', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesAllPseudoTypes */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'false|mixed|self|parent|iterable|Resource', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesIllegalTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + // Missing static, but that's OK as not an allowed syntax. + 'type' => 'callable||void', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8UnionTypesNullable */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int|float', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP8PseudoTypeNull */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'null', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PseudoTypeFalse */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'false', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PseudoTypeFalseAndBool */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'bool|FALSE', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8ObjectAndClass */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'object|ClassName', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PseudoTypeIterableAndArray */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'iterable|array|Traversable', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|string|INT', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81Readonly */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'int', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81ReadonlyWithNullableType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => '?array', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP81ReadonlyWithUnionType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|int', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81ReadonlyWithUnionTypeWithNull */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|null', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81OnlyReadonlyWithUnionType */', + [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|int', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PropertySingleAttribute */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'string', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP8PropertyMultipleAttributes */', + [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int|float', + 'nullable_type' => true, + ], + ], + [ + '/* testPHP8PropertyMultilineAttribute */', + [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'mixed', + 'nullable_type' => false, + ], + ], + [ + '/* testEnumProperty */', + [], + ], + [ + '/* testPHP81IntersectionTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => 'Foo&Bar', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81MoreIntersectionTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => 'Foo&Bar&Baz', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81IllegalIntersectionTypes */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => 'int&string', + 'nullable_type' => false, + ], + ], + [ + '/* testPHP81NulltableIntersectionType */', + [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'type' => '?Foo&Bar', + 'nullable_type' => true, + ], + ], + ]; + + }//end dataGetMemberProperties() + + + /** + * Test receiving an expected exception when a non property is passed. + * + * @param string $identifier Comment which precedes the test case. + * + * @expectedException PHP_CodeSniffer\Exceptions\RuntimeException + * @expectedExceptionMessage $stackPtr is not a class member var + * + * @dataProvider dataNotClassProperty + * + * @return void + */ + public function testNotClassPropertyException($identifier) + { + $variable = $this->getTargetToken($identifier, T_VARIABLE); + $result = self::$phpcsFile->getMemberProperties($variable); + + }//end testNotClassPropertyException() + + + /** + * Data provider for the NotClassPropertyException test. + * + * @see testNotClassPropertyException() + * + * @return array + */ + public function dataNotClassProperty() + { + return [ + ['/* testMethodParam */'], + ['/* testImportedGlobal */'], + ['/* testLocalVariable */'], + ['/* testGlobalVariable */'], + ['/* testNestedMethodParam 1 */'], + ['/* testNestedMethodParam 2 */'], + ['/* testEnumMethodParamNotProperty */'], + ]; + + }//end dataNotClassProperty() + + + /** + * Test receiving an expected exception when a non variable is passed. + * + * @expectedException PHP_CodeSniffer\Exceptions\RuntimeException + * @expectedExceptionMessage $stackPtr must be of type T_VARIABLE + * + * @return void + */ + public function testNotAVariableException() + { + $next = $this->getTargetToken('/* testNotAVariable */', T_RETURN); + $result = self::$phpcsFile->getMemberProperties($next); + + }//end testNotAVariableException() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc new file mode 100644 index 000000000..dc4654914 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc @@ -0,0 +1,164 @@ + $b; + +/* testPHP8MixedTypeHint */ +function mixedTypeHint(mixed &...$var1) {} + +/* testPHP8MixedTypeHintNullable */ +// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. +function mixedTypeHintNullable(?Mixed $var1) {} + +/* testNamespaceOperatorTypeHint */ +function namespaceOperatorTypeHint(?namespace\Name $var1) {} + +/* testPHP8UnionTypesSimple */ +function unionTypeSimple(int|float $number, self|parent &...$obj) {} + +/* testPHP8UnionTypesWithSpreadOperatorAndReference */ +function globalFunctionWithSpreadAndReference(float|null &$paramA, string|int ...$paramB) {} + +/* testPHP8UnionTypesSimpleWithBitwiseOrInDefault */ +$fn = fn(int|float $var = CONSTANT_A | CONSTANT_B) => $var; + +/* testPHP8UnionTypesTwoClasses */ +function unionTypesTwoClasses(MyClassA|\Package\MyClassB $var) {} + +/* testPHP8UnionTypesAllBaseTypes */ +function unionTypesAllBaseTypes(array|bool|callable|int|float|null|object|string $var) {} + +/* testPHP8UnionTypesAllPseudoTypes */ +// Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. +function unionTypesAllPseudoTypes(false|mixed|self|parent|iterable|Resource $var) {} + +/* testPHP8UnionTypesNullable */ +// Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. +$closure = function (?int|float $number) {}; + +/* testPHP8PseudoTypeNull */ +// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeNull(null $var = null) {} + +/* testPHP8PseudoTypeFalse */ +// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeFalse(false $var = false) {} + +/* testPHP8PseudoTypeFalseAndBool */ +// Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. +function pseudoTypeFalseAndBool(bool|false $var = false) {} + +/* testPHP8ObjectAndClass */ +// Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. +function objectAndClass(object|ClassName $var) {} + +/* testPHP8PseudoTypeIterableAndArray */ +// Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. +function pseudoTypeIterableAndArray(iterable|array|Traversable $var) {} + +/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ +// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. +function duplicateTypeInUnion( int | string /*comment*/ | INT $var) {} + +class ConstructorPropertyPromotionNoTypes { + /* testPHP8ConstructorPropertyPromotionNoTypes */ + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + ) {} +} + +class ConstructorPropertyPromotionWithTypes { + /* testPHP8ConstructorPropertyPromotionWithTypes */ + public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {} +} + +class ConstructorPropertyPromotionAndNormalParams { + /* testPHP8ConstructorPropertyPromotionAndNormalParam */ + public function __construct(public int $promotedProp, ?int $normalArg) {} +} + +class ConstructorPropertyPromotionWithReadOnly { + /* testPHP81ConstructorPropertyPromotionWithReadOnly */ + public function __construct(public readonly ?int $promotedProp, readonly private string|bool &$promotedToo) {} +} + +/* testPHP8ConstructorPropertyPromotionGlobalFunction */ +// Intentional fatal error. Property promotion not allowed in non-constructor, but that's not the concern of this method. +function globalFunction(private $x) {} + +abstract class ConstructorPropertyPromotionAbstractMethod { + /* testPHP8ConstructorPropertyPromotionAbstractMethod */ + // Intentional fatal error. + // 1. Property promotion not allowed in abstract method, but that's not the concern of this method. + // 2. Variadic arguments not allowed in property promotion, but that's not the concern of this method. + // 3. The callable type is not supported for properties, but that's not the concern of this method. + abstract public function __construct(public callable $y, private ...$x); +} + +/* testCommentsInParameter */ +function commentsInParams( + // Leading comment. + ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ 'default value' . /*-*/ 'second part' // Trailing comment. +) {} + +/* testParameterAttributesInFunctionDeclaration */ +class ParametersWithAttributes( + public function __construct( + #[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute, + #[MyAttr([1, 2])] + Type|false + $typedParamSingleAttribute, + #[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute, + #[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes, + #[MyAttribute(array("key" => "value"))] + &...$otherParam, + ) {} +} + +/* testPHP8IntersectionTypes */ +function intersectionTypes(Foo&Bar $obj1, Boo&Bar $obj2) {} + +/* testPHP81IntersectionTypesWithSpreadOperatorAndReference */ +function globalFunctionWithSpreadAndReference(Boo&Bar &$paramA, Foo&Bar ...$paramB) {} + +/* testPHP81MoreIntersectionTypes */ +function moreIntersectionTypes(MyClassA&\Package\MyClassB&\Package\MyClassC $var) {} + +/* testPHP81IllegalIntersectionTypes */ +// Intentional fatal error - simple types are not allowed with intersection types, but that's not the concern of the method. +$closure = function (string&int $numeric_string) {}; + +/* testPHP81NullableIntersectionTypes */ +// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method. +$closure = function (?Foo&Bar $object) {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php new file mode 100644 index 000000000..f70d64f2d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php @@ -0,0 +1,1145 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GetMethodParametersTest extends AbstractMethodUnitTest +{ + + + /** + * Verify pass-by-reference parsing. + * + * @return void + */ + public function testPassByReference() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => '&$var', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPassByReference() + + + /** + * Verify array hint parsing. + * + * @return void + */ + public function testArrayHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'array $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'array', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrayHint() + + + /** + * Verify type hint parsing. + * + * @return void + */ + public function testTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => 'foo $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'foo', + 'nullable_type' => false, + ]; + + $expected[1] = [ + 'name' => '$var2', + 'content' => 'bar $var2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'bar', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testTypeHint() + + + /** + * Verify self type hint parsing. + * + * @return void + */ + public function testSelfTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'self $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'self', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testSelfTypeHint() + + + /** + * Verify nullable type hint parsing. + * + * @return void + */ + public function testNullableTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '?int $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + ]; + + $expected[1] = [ + 'name' => '$var2', + 'content' => '?\bar $var2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?\bar', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNullableTypeHint() + + + /** + * Verify variable. + * + * @return void + */ + public function testVariable() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => '$var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testVariable() + + + /** + * Verify default value parsing with a single function param. + * + * @return void + */ + public function testSingleDefaultValue() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '$var1=self::CONSTANT', + 'has_attributes' => false, + 'default' => 'self::CONSTANT', + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testSingleDefaultValue() + + + /** + * Verify default value parsing. + * + * @return void + */ + public function testDefaultValues() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '$var1=1', + 'has_attributes' => false, + 'default' => '1', + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$var2', + 'content' => "\$var2='value'", + 'has_attributes' => false, + 'default' => "'value'", + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testDefaultValues() + + + /** + * Verify "bitwise and" in default value !== pass-by-reference. + * + * @return void + */ + public function testBitwiseAndConstantExpressionDefaultValue() + { + $expected = []; + $expected[0] = [ + 'name' => '$a', + 'content' => '$a = 10 & 20', + 'default' => '10 & 20', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBitwiseAndConstantExpressionDefaultValue() + + + /** + * Verify that arrow functions are supported. + * + * @return void + */ + public function testArrowFunction() + { + $expected = []; + $expected[0] = [ + 'name' => '$a', + 'content' => 'int $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int', + 'nullable_type' => false, + ]; + + $expected[1] = [ + 'name' => '$b', + 'content' => '...$b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunction() + + + /** + * Verify recognition of PHP8 mixed type declaration. + * + * @return void + */ + public function testPHP8MixedTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => 'mixed &...$var1', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => 'mixed', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHint() + + + /** + * Verify recognition of PHP8 mixed type declaration with nullability. + * + * @return void + */ + public function testPHP8MixedTypeHintNullable() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '?Mixed $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?Mixed', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHintNullable() + + + /** + * Verify recognition of type declarations using the namespace operator. + * + * @return void + */ + public function testNamespaceOperatorTypeHint() + { + $expected = []; + $expected[0] = [ + 'name' => '$var1', + 'content' => '?namespace\Name $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?namespace\Name', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNamespaceOperatorTypeHint() + + + /** + * Verify recognition of PHP8 union type declaration. + * + * @return void + */ + public function testPHP8UnionTypesSimple() + { + $expected = []; + $expected[0] = [ + 'name' => '$number', + 'content' => 'int|float $number', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int|float', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$obj', + 'content' => 'self|parent &...$obj', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => 'self|parent', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimple() + + + /** + * Verify recognition of PHP8 union type declaration when the variable has either a spread operator or a reference. + * + * @return void + */ + public function testPHP8UnionTypesWithSpreadOperatorAndReference() + { + $expected = []; + $expected[0] = [ + 'name' => '$paramA', + 'content' => 'float|null &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => 'float|null', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$paramB', + 'content' => 'string|int ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => 'string|int', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP8 union type declaration with a bitwise or in the default value. + * + * @return void + */ + public function testPHP8UnionTypesSimpleWithBitwiseOrInDefault() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'int|float $var = CONSTANT_A | CONSTANT_B', + 'default' => 'CONSTANT_A | CONSTANT_B', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int|float', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimpleWithBitwiseOrInDefault() + + + /** + * Verify recognition of PHP8 union type declaration with two classes. + * + * @return void + */ + public function testPHP8UnionTypesTwoClasses() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'MyClassA|\Package\MyClassB $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'MyClassA|\Package\MyClassB', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesTwoClasses() + + + /** + * Verify recognition of PHP8 union type declaration with all base types. + * + * @return void + */ + public function testPHP8UnionTypesAllBaseTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'array|bool|callable|int|float|null|object|string $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'array|bool|callable|int|float|null|object|string', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllBaseTypes() + + + /** + * Verify recognition of PHP8 union type declaration with all pseudo types. + * + * @return void + */ + public function testPHP8UnionTypesAllPseudoTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'false|mixed|self|parent|iterable|Resource $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'false|mixed|self|parent|iterable|Resource', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllPseudoTypes() + + + /** + * Verify recognition of PHP8 union type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP8UnionTypesNullable() + { + $expected = []; + $expected[0] = [ + 'name' => '$number', + 'content' => '?int|float $number', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int|float', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesNullable() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type null. + * + * @return void + */ + public function testPHP8PseudoTypeNull() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'null $var = null', + 'default' => 'null', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'null', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeNull() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type false. + * + * @return void + */ + public function testPHP8PseudoTypeFalse() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'false $var = false', + 'default' => 'false', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'false', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalse() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. + * + * @return void + */ + public function testPHP8PseudoTypeFalseAndBool() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'bool|false $var = false', + 'default' => 'false', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'bool|false', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalseAndBool() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. + * + * @return void + */ + public function testPHP8ObjectAndClass() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'object|ClassName $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'object|ClassName', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ObjectAndClass() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. + * + * @return void + */ + public function testPHP8PseudoTypeIterableAndArray() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'iterable|array|Traversable $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'iterable|array|Traversable', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeIterableAndArray() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) duplicate types. + * + * @return void + */ + public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'int | string /*comment*/ | INT $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int|string|INT', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() + + + /** + * Verify recognition of PHP8 constructor property promotion without type declaration, with defaults. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionNoTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$x', + 'content' => 'public $x = 0.0', + 'default' => '0.0', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'public', + 'property_readonly' => false, + ]; + $expected[1] = [ + 'name' => '$y', + 'content' => 'protected $y = \'\'', + 'default' => "''", + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'protected', + 'property_readonly' => false, + ]; + $expected[2] = [ + 'name' => '$z', + 'content' => 'private $z = null', + 'default' => 'null', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'private', + 'property_readonly' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionNoTypes() + + + /** + * Verify recognition of PHP8 constructor property promotion with type declarations. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionWithTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$x', + 'content' => 'protected float|int $x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'float|int', + 'nullable_type' => false, + 'property_visibility' => 'protected', + 'property_readonly' => false, + ]; + $expected[1] = [ + 'name' => '$y', + 'content' => 'public ?string &$y = \'test\'', + 'default' => "'test'", + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => '?string', + 'nullable_type' => true, + 'property_visibility' => 'public', + 'property_readonly' => false, + ]; + $expected[2] = [ + 'name' => '$z', + 'content' => 'private mixed $z', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'mixed', + 'nullable_type' => false, + 'property_visibility' => 'private', + 'property_readonly' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionWithTypes() + + + /** + * Verify recognition of PHP8 constructor with both property promotion as well as normal parameters. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionAndNormalParam() + { + $expected = []; + $expected[0] = [ + 'name' => '$promotedProp', + 'content' => 'public int $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'int', + 'nullable_type' => false, + 'property_visibility' => 'public', + 'property_readonly' => false, + ]; + $expected[1] = [ + 'name' => '$normalArg', + 'content' => '?int $normalArg', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionAndNormalParam() + + + /** + * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly keyword. + * + * @return void + */ + public function testPHP81ConstructorPropertyPromotionWithReadOnly() + { + $expected = []; + $expected[0] = [ + 'name' => '$promotedProp', + 'content' => 'public readonly ?int $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + 'property_visibility' => 'public', + 'property_readonly' => true, + ]; + $expected[1] = [ + 'name' => '$promotedToo', + 'content' => 'readonly private string|bool &$promotedToo', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => 'string|bool', + 'nullable_type' => false, + 'property_visibility' => 'private', + 'property_readonly' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81ConstructorPropertyPromotionWithReadOnly() + + + /** + * Verify behaviour when a non-constructor function uses PHP 8 property promotion syntax. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionGlobalFunction() + { + $expected = []; + $expected[0] = [ + 'name' => '$x', + 'content' => 'private $x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'private', + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionGlobalFunction() + + + /** + * Verify behaviour when an abstract constructor uses PHP 8 property promotion syntax. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionAbstractMethod() + { + $expected = []; + $expected[0] = [ + 'name' => '$y', + 'content' => 'public callable $y', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'callable', + 'nullable_type' => false, + 'property_visibility' => 'public', + ]; + $expected[1] = [ + 'name' => '$x', + 'content' => 'private ...$x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => '', + 'nullable_type' => false, + 'property_visibility' => 'private', + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionAbstractMethod() + + + /** + * Verify and document behaviour when there are comments within a parameter declaration. + * + * @return void + */ + public function testCommentsInParameter() + { + $expected = []; + $expected[0] = [ + 'name' => '$param', + 'content' => '// Leading comment. + ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ \'default value\' . /*-*/ \'second part\' // Trailing comment.', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => '?MyClass', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testCommentsInParameter() + + + /** + * Verify behaviour when parameters have attributes attached. + * + * @return void + */ + public function testParameterAttributesInFunctionDeclaration() + { + $expected = []; + $expected[0] = [ + 'name' => '$constructorPropPromTypedParamSingleAttribute', + 'content' => '#[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'string', + 'nullable_type' => false, + 'property_visibility' => 'private', + ]; + $expected[1] = [ + 'name' => '$typedParamSingleAttribute', + 'content' => '#[MyAttr([1, 2])] + Type|false + $typedParamSingleAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'Type|false', + 'nullable_type' => false, + ]; + $expected[2] = [ + 'name' => '$nullableTypedParamMultiAttribute', + 'content' => '#[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?int', + 'nullable_type' => true, + ]; + $expected[3] = [ + 'name' => '$nonTypedParamTwoAttributes', + 'content' => '#[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '', + 'nullable_type' => false, + ]; + $expected[4] = [ + 'name' => '$otherParam', + 'content' => '#[MyAttribute(array("key" => "value"))] + &...$otherParam', + 'has_attributes' => true, + 'pass_by_reference' => true, + 'variable_length' => true, + 'type_hint' => '', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testParameterAttributesInFunctionDeclaration() + + + /** + * Verify recognition of PHP8.1 intersection type declaration. + * + * @return void + */ + public function testPHP8IntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$obj1', + 'content' => 'Foo&Bar $obj1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'Foo&Bar', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$obj2', + 'content' => 'Boo&Bar $obj2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'Boo&Bar', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8IntersectionTypes() + + + /** + * Verify recognition of PHP8 intersection type declaration when the variable has either a spread operator or a reference. + * + * @return void + */ + public function testPHP81IntersectionTypesWithSpreadOperatorAndReference() + { + $expected = []; + $expected[0] = [ + 'name' => '$paramA', + 'content' => 'Boo&Bar &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'variable_length' => false, + 'type_hint' => 'Boo&Bar', + 'nullable_type' => false, + ]; + $expected[1] = [ + 'name' => '$paramB', + 'content' => 'Foo&Bar ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => true, + 'type_hint' => 'Foo&Bar', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IntersectionTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with more types. + * + * @return void + */ + public function testPHP81MoreIntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$var', + 'content' => 'MyClassA&\Package\MyClassB&\Package\MyClassC $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81MoreIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. + * + * @return void + */ + public function testPHP81IllegalIntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$numeric_string', + 'content' => 'string&int $numeric_string', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => 'string&int', + 'nullable_type' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IllegalIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableIntersectionTypes() + { + $expected = []; + $expected[0] = [ + 'name' => '$object', + 'content' => '?Foo&Bar $object', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'variable_length' => false, + 'type_hint' => '?Foo&Bar', + 'nullable_type' => true, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableIntersectionTypes() + + + /** + * Test helper. + * + * @param string $commentString The comment which preceeds the test. + * @param array $expected The expected function output. + * + * @return void + */ + private function getMethodParametersTestHelper($commentString, $expected) + { + $function = $this->getTargetToken($commentString, [T_FUNCTION, T_CLOSURE, T_FN]); + $found = self::$phpcsFile->getMethodParameters($function); + + $this->assertArraySubset($expected, $found, true); + + }//end getMethodParametersTestHelper() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc new file mode 100644 index 000000000..0c592369a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc @@ -0,0 +1,152 @@ + $number + 1, + $numbers +); + +class ReturnMe { + /* testReturnTypeStatic */ + private function myFunction(): static { + return $this; + } +} + +/* testPHP8MixedTypeHint */ +function mixedTypeHint() :mixed {} + +/* testPHP8MixedTypeHintNullable */ +// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. +function mixedTypeHintNullable(): ?mixed {} + +/* testNamespaceOperatorTypeHint */ +function namespaceOperatorTypeHint() : ?namespace\Name {} + +/* testPHP8UnionTypesSimple */ +function unionTypeSimple($number) : int|float {} + +/* testPHP8UnionTypesTwoClasses */ +$fn = fn($var): MyClassA|\Package\MyClassB => $var; + +/* testPHP8UnionTypesAllBaseTypes */ +function unionTypesAllBaseTypes() : array|bool|callable|int|float|null|Object|string {} + +/* testPHP8UnionTypesAllPseudoTypes */ +// Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. +function unionTypesAllPseudoTypes($var) : false|MIXED|self|parent|static|iterable|Resource|void {} + +/* testPHP8UnionTypesNullable */ +// Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. +$closure = function () use($a) :?int|float {}; + +/* testPHP8PseudoTypeNull */ +// Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeNull(): null {} + +/* testPHP8PseudoTypeFalse */ +// Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeFalse(): false {} + +/* testPHP8PseudoTypeFalseAndBool */ +// Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. +function pseudoTypeFalseAndBool(): bool|false {} + +/* testPHP8ObjectAndClass */ +// Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. +function objectAndClass(): object|ClassName {} + +/* testPHP8PseudoTypeIterableAndArray */ +// Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. +interface FooBar { + public function pseudoTypeIterableAndArray(): iterable|array|Traversable; +} + +/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ +// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. +function duplicateTypeInUnion(): int | /*comment*/ string | INT {} + +/* testPHP81NeverType */ +function never(): never {} + +/* testPHP81NullableNeverType */ +// Intentional fatal error - nullability is not allowed with never, but that's not the concern of the method. +function nullableNever(): ?never {} + +/* testPHP8IntersectionTypes */ +function intersectionTypes(): Foo&Bar {} + +/* testPHP81MoreIntersectionTypes */ +function moreIntersectionTypes(): MyClassA&\Package\MyClassB&\Package\MyClassC {} + +/* testPHP81IntersectionArrowFunction */ +$fn = fn($var): MyClassA&\Package\MyClassB => $var; + +/* testPHP81IllegalIntersectionTypes */ +// Intentional fatal error - simple types are not allowed with intersection types, but that's not the concern of the method. +$closure = function (): string&int {}; + +/* testPHP81NullableIntersectionTypes */ +// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method. +$closure = function (): ?Foo&Bar {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php new file mode 100644 index 000000000..2f552bfec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php @@ -0,0 +1,911 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GetMethodPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test a basic function. + * + * @return void + */ + public function testBasicFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBasicFunction() + + + /** + * Test a function with a return type. + * + * @return void + */ + public function testReturnFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnFunction() + + + /** + * Test a closure used as a function argument. + * + * @return void + */ + public function testNestedClosure() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNestedClosure() + + + /** + * Test a basic method. + * + * @return void + */ + public function testBasicMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBasicMethod() + + + /** + * Test a private static method. + * + * @return void + */ + public function testPrivateStaticMethod() + { + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => true, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPrivateStaticMethod() + + + /** + * Test a basic final method. + * + * @return void + */ + public function testFinalMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => true, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testFinalMethod() + + + /** + * Test a protected method with a return type. + * + * @return void + */ + public function testProtectedReturnMethod() + { + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testProtectedReturnMethod() + + + /** + * Test a public method with a return type. + * + * @return void + */ + public function testPublicReturnMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'array', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPublicReturnMethod() + + + /** + * Test a public method with a nullable return type. + * + * @return void + */ + public function testNullableReturnMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '?array', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNullableReturnMethod() + + + /** + * Test a public method with a nullable return type. + * + * @return void + */ + public function testMessyNullableReturnMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '?array', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testMessyNullableReturnMethod() + + + /** + * Test a method with a namespaced return type. + * + * @return void + */ + public function testReturnNamespace() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '\MyNamespace\MyClass', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnNamespace() + + + /** + * Test a method with a messy namespaces return type. + * + * @return void + */ + public function testReturnMultilineNamespace() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '\MyNamespace\MyClass\Foo', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnMultilineNamespace() + + + /** + * Test a basic abstract method. + * + * @return void + */ + public function testAbstractMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testAbstractMethod() + + + /** + * Test an abstract method with a return type. + * + * @return void + */ + public function testAbstractReturnMethod() + { + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'bool', + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testAbstractReturnMethod() + + + /** + * Test a basic interface method. + * + * @return void + */ + public function testInterfaceMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testInterfaceMethod() + + + /** + * Test a static arrow function. + * + * @return void + */ + public function testArrowFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => true, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunction() + + + /** + * Test a function with return type "static". + * + * @return void + */ + public function testReturnTypeStatic() + { + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => 'static', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnTypeStatic() + + + /** + * Test a function with return type "mixed". + * + * @return void + */ + public function testPHP8MixedTypeHint() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'mixed', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHint() + + + /** + * Test a function with return type "mixed" and nullability. + * + * @return void + */ + public function testPHP8MixedTypeHintNullable() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?mixed', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHintNullable() + + + /** + * Test a function with return type using the namespace operator. + * + * @return void + */ + public function testNamespaceOperatorTypeHint() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?namespace\Name', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNamespaceOperatorTypeHint() + + + /** + * Verify recognition of PHP8 union type declaration. + * + * @return void + */ + public function testPHP8UnionTypesSimple() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int|float', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimple() + + + /** + * Verify recognition of PHP8 union type declaration with two classes. + * + * @return void + */ + public function testPHP8UnionTypesTwoClasses() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA|\Package\MyClassB', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesTwoClasses() + + + /** + * Verify recognition of PHP8 union type declaration with all base types. + * + * @return void + */ + public function testPHP8UnionTypesAllBaseTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array|bool|callable|int|float|null|Object|string', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllBaseTypes() + + + /** + * Verify recognition of PHP8 union type declaration with all pseudo types. + * + * @return void + */ + public function testPHP8UnionTypesAllPseudoTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'false|MIXED|self|parent|static|iterable|Resource|void', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllPseudoTypes() + + + /** + * Verify recognition of PHP8 union type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP8UnionTypesNullable() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?int|float', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesNullable() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type null. + * + * @return void + */ + public function testPHP8PseudoTypeNull() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'null', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeNull() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type false. + * + * @return void + */ + public function testPHP8PseudoTypeFalse() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'false', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalse() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. + * + * @return void + */ + public function testPHP8PseudoTypeFalseAndBool() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'bool|false', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalseAndBool() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. + * + * @return void + */ + public function testPHP8ObjectAndClass() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'object|ClassName', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ObjectAndClass() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. + * + * @return void + */ + public function testPHP8PseudoTypeIterableAndArray() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'iterable|array|Traversable', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeIterableAndArray() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) duplicate types. + * + * @return void + */ + public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int|string|INT', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() + + + /** + * Verify recognition of PHP8.1 type "never". + * + * @return void + */ + public function testPHP81NeverType() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'never', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NeverType() + + + /** + * Verify recognition of PHP8.1 type "never" with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableNeverType() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?never', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableNeverType() + + + /** + /** + * Verify recognition of PHP8.1 intersection type declaration. + * + * @return void + */ + public function testPHP8IntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'Foo&Bar', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8IntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with more types. + * + * @return void + */ + public function testPHP81MoreIntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81MoreIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration in arrow function. + * + * @return void + */ + public function testPHP81IntersectionArrowFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA&\Package\MyClassB', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IntersectionArrowFunction() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. + * + * @return void + */ + public function testPHP81IllegalIntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'string&int', + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IllegalIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableIntersectionTypes() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?Foo&Bar', + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableIntersectionTypes() + + + /** + * Test helper. + * + * @param string $commentString The comment which preceeds the test. + * @param array $expected The expected function output. + * + * @return void + */ + private function getMethodPropertiesTestHelper($commentString, $expected) + { + $function = $this->getTargetToken($commentString, [T_FUNCTION, T_CLOSURE, T_FN]); + $found = self::$phpcsFile->getMethodProperties($function); + + $this->assertArraySubset($expected, $found, true); + + }//end getMethodPropertiesTestHelper() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc new file mode 100644 index 000000000..cd40ed3ba --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc @@ -0,0 +1,150 @@ + $first, 'b' => $something & $somethingElse ]; + +/* testBitwiseAndF */ +$a = array( 'a' => $first, 'b' => $something & \MyClass::$somethingElse ); + +/* testBitwiseAndG */ +$a = $something & $somethingElse; + +/* testBitwiseAndH */ +function myFunction($a = 10 & 20) {} + +/* testBitwiseAndI */ +$closure = function ($a = MY_CONSTANT & parent::OTHER_CONSTANT) {}; + +/* testFunctionReturnByReference */ +function &myFunction() {} + +/* testFunctionPassByReferenceA */ +function myFunction( &$a ) {} + +/* testFunctionPassByReferenceB */ +function myFunction( $a, &$b ) {} + +/* testFunctionPassByReferenceC */ +$closure = function ( &$a ) {}; + +/* testFunctionPassByReferenceD */ +$closure = function ( $a, &$b ) {}; + +/* testFunctionPassByReferenceE */ +function myFunction(array &$one) {} + +/* testFunctionPassByReferenceF */ +$closure = function (\MyClass &$one) {}; + +/* testFunctionPassByReferenceG */ +$closure = function myFunc($param, &...$moreParams) {}; + +/* testForeachValueByReference */ +foreach( $array as $key => &$value ) {} + +/* testForeachKeyByReference */ +foreach( $array as &$key => $value ) {} + +/* testArrayValueByReferenceA */ +$a = [ 'a' => &$something ]; + +/* testArrayValueByReferenceB */ +$a = [ 'a' => $something, 'b' => &$somethingElse ]; + +/* testArrayValueByReferenceC */ +$a = [ &$something ]; + +/* testArrayValueByReferenceD */ +$a = [ $something, &$somethingElse ]; + +/* testArrayValueByReferenceE */ +$a = array( 'a' => &$something ); + +/* testArrayValueByReferenceF */ +$a = array( 'a' => $something, 'b' => &$somethingElse ); + +/* testArrayValueByReferenceG */ +$a = array( &$something ); + +/* testArrayValueByReferenceH */ +$a = array( $something, &$somethingElse ); + +/* testAssignByReferenceA */ +$b = &$something; + +/* testAssignByReferenceB */ +$b =& $something; + +/* testAssignByReferenceC */ +$b .= &$something; + +/* testAssignByReferenceD */ +$myValue = &$obj->getValue(); + +/* testAssignByReferenceE */ +$collection = &collector(); + +/* testPassByReferenceA */ +functionCall(&$something, $somethingElse); + +/* testPassByReferenceB */ +functionCall($something, &$somethingElse); + +/* testPassByReferenceC */ +functionCall($something, &$this->somethingElse); + +/* testPassByReferenceD */ +functionCall($something, &self::$somethingElse); + +/* testPassByReferenceE */ +functionCall($something, &parent::$somethingElse); + +/* testPassByReferenceF */ +functionCall($something, &static::$somethingElse); + +/* testPassByReferenceG */ +functionCall($something, &SomeClass::$somethingElse); + +/* testPassByReferenceH */ +functionCall(&\SomeClass::$somethingElse); + +/* testPassByReferenceI */ +functionCall($something, &\SomeNS\SomeClass::$somethingElse); + +/* testPassByReferenceJ */ +functionCall($something, &namespace\SomeClass::$somethingElse); + +/* testNewByReferenceA */ +$foobar2 = &new Foobar(); + +/* testNewByReferenceB */ +functionCall( $something , &new Foobar() ); + +/* testUseByReference */ +$closure = function() use (&$var){}; + +/* testArrowFunctionReturnByReference */ +fn&($x) => $x; + +/* testArrowFunctionPassByReferenceA */ +$fn = fn(array &$one) => 1; + +/* testArrowFunctionPassByReferenceB */ +$fn = fn($param, &...$moreParams) => 1; + +/* testClosureReturnByReference */ +$closure = function &($param) use ($value) {}; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php new file mode 100644 index 000000000..ea2dddbad --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php @@ -0,0 +1,248 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class IsReferenceTest extends AbstractMethodUnitTest +{ + + + /** + * Test correctly identifying whether a "bitwise and" token is a reference or not. + * + * @param string $identifier Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataIsReference + * + * @return void + */ + public function testIsReference($identifier, $expected) + { + $bitwiseAnd = $this->getTargetToken($identifier, T_BITWISE_AND); + $result = self::$phpcsFile->isReference($bitwiseAnd); + $this->assertSame($expected, $result); + + }//end testIsReference() + + + /** + * Data provider for the IsReference test. + * + * @see testIsReference() + * + * @return array + */ + public function dataIsReference() + { + return [ + [ + '/* testBitwiseAndA */', + false, + ], + [ + '/* testBitwiseAndB */', + false, + ], + [ + '/* testBitwiseAndC */', + false, + ], + [ + '/* testBitwiseAndD */', + false, + ], + [ + '/* testBitwiseAndE */', + false, + ], + [ + '/* testBitwiseAndF */', + false, + ], + [ + '/* testBitwiseAndG */', + false, + ], + [ + '/* testBitwiseAndH */', + false, + ], + [ + '/* testBitwiseAndI */', + false, + ], + [ + '/* testFunctionReturnByReference */', + true, + ], + [ + '/* testFunctionPassByReferenceA */', + true, + ], + [ + '/* testFunctionPassByReferenceB */', + true, + ], + [ + '/* testFunctionPassByReferenceC */', + true, + ], + [ + '/* testFunctionPassByReferenceD */', + true, + ], + [ + '/* testFunctionPassByReferenceE */', + true, + ], + [ + '/* testFunctionPassByReferenceF */', + true, + ], + [ + '/* testFunctionPassByReferenceG */', + true, + ], + [ + '/* testForeachValueByReference */', + true, + ], + [ + '/* testForeachKeyByReference */', + true, + ], + [ + '/* testArrayValueByReferenceA */', + true, + ], + [ + '/* testArrayValueByReferenceB */', + true, + ], + [ + '/* testArrayValueByReferenceC */', + true, + ], + [ + '/* testArrayValueByReferenceD */', + true, + ], + [ + '/* testArrayValueByReferenceE */', + true, + ], + [ + '/* testArrayValueByReferenceF */', + true, + ], + [ + '/* testArrayValueByReferenceG */', + true, + ], + [ + '/* testArrayValueByReferenceH */', + true, + ], + [ + '/* testAssignByReferenceA */', + true, + ], + [ + '/* testAssignByReferenceB */', + true, + ], + [ + '/* testAssignByReferenceC */', + true, + ], + [ + '/* testAssignByReferenceD */', + true, + ], + [ + '/* testAssignByReferenceE */', + true, + ], + [ + '/* testPassByReferenceA */', + true, + ], + [ + '/* testPassByReferenceB */', + true, + ], + [ + '/* testPassByReferenceC */', + true, + ], + [ + '/* testPassByReferenceD */', + true, + ], + [ + '/* testPassByReferenceE */', + true, + ], + [ + '/* testPassByReferenceF */', + true, + ], + [ + '/* testPassByReferenceG */', + true, + ], + [ + '/* testPassByReferenceH */', + true, + ], + [ + '/* testPassByReferenceI */', + true, + ], + [ + '/* testPassByReferenceJ */', + true, + ], + [ + '/* testNewByReferenceA */', + true, + ], + [ + '/* testNewByReferenceB */', + true, + ], + [ + '/* testUseByReference */', + true, + ], + [ + '/* testArrowFunctionReturnByReference */', + true, + ], + [ + '/* testArrowFunctionPassByReferenceA */', + true, + ], + [ + '/* testArrowFunctionPassByReferenceB */', + true, + ], + [ + '/* testClosureReturnByReference */', + true, + ], + ]; + + }//end dataIsReference() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php new file mode 100644 index 000000000..2c9f57cd3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php @@ -0,0 +1,154 @@ + + * @author Juliette Reinders Folmer + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Filters\Filter; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Filters\Filter; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class AcceptTest extends TestCase +{ + + /** + * The Config object. + * + * @var \PHP_CodeSniffer\Config + */ + protected static $config; + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected static $ruleset; + + + /** + * Initialize the test. + * + * @return void + */ + public function setUp() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + }//end setUp() + + + /** + * Initialize the config and ruleset objects based on the `AcceptTest.xml` ruleset file. + * + * @return void + */ + public static function setUpBeforeClass() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // This test will be skipped. + return; + } + + $standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + self::$config = new Config(["--standard=$standard", "--ignore=*/somethingelse/*"]); + self::$ruleset = new Ruleset(self::$config); + + }//end setUpBeforeClass() + + + /** + * Test filtering a file list for excluded paths. + * + * @param array $inputPaths List of file paths to be filtered. + * @param array $expectedOutput Expected filtering result. + * + * @dataProvider dataExcludePatterns + * + * @return void + */ + public function testExcludePatterns($inputPaths, $expectedOutput) + { + $fakeDI = new \RecursiveArrayIterator($inputPaths); + $filter = new Filter($fakeDI, '/', self::$config, self::$ruleset); + $iterator = new \RecursiveIteratorIterator($filter); + $files = []; + + foreach ($iterator as $file) { + $files[] = $file; + } + + $this->assertEquals($expectedOutput, $files); + + }//end testExcludePatterns() + + + /** + * Data provider. + * + * @see testExcludePatterns + * + * @return array + */ + public function dataExcludePatterns() + { + $testCases = [ + // Test top-level exclude patterns. + [ + [ + '/path/to/src/Main.php', + '/path/to/src/Something/Main.php', + '/path/to/src/Somethingelse/Main.php', + '/path/to/src/SomethingelseEvenLonger/Main.php', + '/path/to/src/Other/Main.php', + ], + [ + '/path/to/src/Main.php', + '/path/to/src/SomethingelseEvenLonger/Main.php', + ], + ], + + // Test ignoring standard/sniff specific exclude patterns. + [ + [ + '/path/to/src/generic-project/Main.php', + '/path/to/src/generic/Main.php', + '/path/to/src/anything-generic/Main.php', + ], + [ + '/path/to/src/generic-project/Main.php', + '/path/to/src/generic/Main.php', + '/path/to/src/anything-generic/Main.php', + ], + ], + ]; + + // Allow these tests to work on Windows as well. + if (DIRECTORY_SEPARATOR === '\\') { + foreach ($testCases as $key => $case) { + foreach ($case as $nr => $param) { + foreach ($param as $file => $value) { + $testCases[$key][$nr][$file] = strtr($value, '/', '\\'); + } + } + } + } + + return $testCases; + + }//end dataExcludePatterns() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml new file mode 100644 index 000000000..3d3e1de08 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml @@ -0,0 +1,16 @@ + + + Ruleset to test the filtering based on exclude patterns. + + + */something/* + + */Other/Main\.php$ + + + + /anything/* + + /YetAnother/Main\.php + + diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php new file mode 100644 index 000000000..b60d524b0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php @@ -0,0 +1,135 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +class IsCamelCapsTest extends TestCase +{ + + + /** + * Test valid public function/method names. + * + * @return void + */ + public function testValidNotClassFormatPublic() + { + $this->assertTrue(Common::isCamelCaps('thisIsCamelCaps', false, true, true)); + $this->assertTrue(Common::isCamelCaps('thisISCamelCaps', false, true, false)); + + }//end testValidNotClassFormatPublic() + + + /** + * Test invalid public function/method names. + * + * @return void + */ + public function testInvalidNotClassFormatPublic() + { + $this->assertFalse(Common::isCamelCaps('_thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('thisISCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('ThisIsCamelCaps', false, true, true)); + + $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, true, true)); + + $this->assertFalse(Common::isCamelCaps('this*IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this-IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this_IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this_is_camel_caps', false, true, true)); + + }//end testInvalidNotClassFormatPublic() + + + /** + * Test valid private method names. + * + * @return void + */ + public function testValidNotClassFormatPrivate() + { + $this->assertTrue(Common::isCamelCaps('_thisIsCamelCaps', false, false, true)); + $this->assertTrue(Common::isCamelCaps('_thisISCamelCaps', false, false, false)); + $this->assertTrue(Common::isCamelCaps('_i18N', false, false, true)); + $this->assertTrue(Common::isCamelCaps('_i18n', false, false, true)); + + }//end testValidNotClassFormatPrivate() + + + /** + * Test invalid private method names. + * + * @return void + */ + public function testInvalidNotClassFormatPrivate() + { + $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_thisISCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('__thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('__thisISCamelCaps', false, false, false)); + + $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_this_is_camel_caps', false, false, true)); + + }//end testInvalidNotClassFormatPrivate() + + + /** + * Test valid class names. + * + * @return void + */ + public function testValidClassFormatPublic() + { + $this->assertTrue(Common::isCamelCaps('ThisIsCamelCaps', true, true, true)); + $this->assertTrue(Common::isCamelCaps('ThisISCamelCaps', true, true, false)); + $this->assertTrue(Common::isCamelCaps('This3IsCamelCaps', true, true, false)); + + }//end testValidClassFormatPublic() + + + /** + * Test invalid class names. + * + * @return void + */ + public function testInvalidClassFormat() + { + $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', true)); + $this->assertFalse(Common::isCamelCaps('This-IsCamelCaps', true)); + $this->assertFalse(Common::isCamelCaps('This_Is_Camel_Caps', true)); + + }//end testInvalidClassFormat() + + + /** + * Test invalid class names with the private flag set. + * + * Note that the private flag is ignored if the class format + * flag is set, so these names are all invalid. + * + * @return void + */ + public function testInvalidClassFormatPrivate() + { + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, true)); + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, false)); + + }//end testInvalidClassFormatPrivate() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php new file mode 100644 index 000000000..8b138e0b0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php @@ -0,0 +1,118 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class RuleInclusionAbsoluteLinuxTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private $contents = ''; + + + /** + * Initialize the config and ruleset objects. + * + * @return void + */ + public function setUp() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + $this->standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + $repoRootDir = dirname(dirname(dirname(__DIR__))); + + // On-the-fly adjust the ruleset test file to be able to test sniffs included with absolute paths. + $contents = file_get_contents($this->standard); + $this->contents = $contents; + + $newPath = $repoRootDir; + if (DIRECTORY_SEPARATOR === '\\') { + $newPath = str_replace('\\', '/', $repoRootDir); + } + + $adjusted = str_replace('%path_slash_forward%', $newPath, $contents); + + if (file_put_contents($this->standard, $adjusted) === false) { + $this->markTestSkipped('On the fly ruleset adjustment failed'); + } + + // Initialize the config and ruleset objects for the test. + $config = new Config(["--standard={$this->standard}"]); + $this->ruleset = new Ruleset($config); + + }//end setUp() + + + /** + * Reset ruleset file. + * + * @return void + */ + public function tearDown() + { + file_put_contents($this->standard, $this->contents); + + }//end tearDown() + + + /** + * Test that sniffs registed with a Linux absolute path are correctly recognized and that + * properties are correctly set for them. + * + * @return void + */ + public function testLinuxStylePathRuleInclusion() + { + // Test that the sniff is correctly registered. + $this->assertObjectHasAttribute('sniffCodes', $this->ruleset); + $this->assertCount(1, $this->ruleset->sniffCodes); + $this->assertArrayHasKey('Generic.Formatting.SpaceAfterNot', $this->ruleset->sniffCodes); + $this->assertSame( + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff', + $this->ruleset->sniffCodes['Generic.Formatting.SpaceAfterNot'] + ); + + // Test that the sniff properties are correctly set. + $this->assertSame( + '10', + $this->ruleset->sniffs['PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff']->spacing + ); + + }//end testLinuxStylePathRuleInclusion() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml new file mode 100644 index 000000000..64d1aae68 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php new file mode 100644 index 000000000..f8e3255b8 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php @@ -0,0 +1,119 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class RuleInclusionAbsoluteWindowsTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private $contents = ''; + + + /** + * Initialize the config and ruleset objects. + * + * @return void + */ + public function setUp() + { + if (DIRECTORY_SEPARATOR === '/') { + $this->markTestSkipped('Windows specific test'); + } + + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + $this->standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + $repoRootDir = dirname(dirname(dirname(__DIR__))); + + // On-the-fly adjust the ruleset test file to be able to test sniffs included with absolute paths. + $contents = file_get_contents($this->standard); + $this->contents = $contents; + + $adjusted = str_replace('%path_slash_back%', $repoRootDir, $contents); + + if (file_put_contents($this->standard, $adjusted) === false) { + $this->markTestSkipped('On the fly ruleset adjustment failed'); + } + + // Initialize the config and ruleset objects for the test. + $config = new Config(["--standard={$this->standard}"]); + $this->ruleset = new Ruleset($config); + + }//end setUp() + + + /** + * Reset ruleset file. + * + * @return void + */ + public function tearDown() + { + if (DIRECTORY_SEPARATOR !== '/') { + file_put_contents($this->standard, $this->contents); + } + + }//end tearDown() + + + /** + * Test that sniffs registed with a Windows absolute path are correctly recognized and that + * properties are correctly set for them. + * + * @return void + */ + public function testWindowsStylePathRuleInclusion() + { + // Test that the sniff is correctly registered. + $this->assertObjectHasAttribute('sniffCodes', $this->ruleset); + $this->assertCount(1, $this->ruleset->sniffCodes); + $this->assertArrayHasKey('Generic.Formatting.SpaceAfterCast', $this->ruleset->sniffCodes); + $this->assertSame( + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff', + $this->ruleset->sniffCodes['Generic.Formatting.SpaceAfterCast'] + ); + + // Test that the sniff property is correctly set. + $this->assertSame( + '10', + $this->ruleset->sniffs['PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff']->spacing + ); + + }//end testWindowsStylePathRuleInclusion() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml new file mode 100644 index 000000000..15710d209 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml new file mode 100644 index 000000000..ca116d45e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php new file mode 100644 index 000000000..24abe8dab --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php @@ -0,0 +1,297 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHPUnit\Framework\TestCase; + +class RuleInclusionTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected static $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private static $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private static $contents = ''; + + + /** + * Initialize the test. + * + * @return void + */ + public function setUp() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // PEAR installs test and sniff files into different locations + // so these tests will not pass as they directly reference files + // by relative location. + $this->markTestSkipped('Test cannot run from a PEAR install'); + } + + }//end setUp() + + + /** + * Initialize the config and ruleset objects based on the `RuleInclusionTest.xml` ruleset file. + * + * @return void + */ + public static function setUpBeforeClass() + { + if ($GLOBALS['PHP_CODESNIFFER_PEAR'] === true) { + // This test will be skipped. + return; + } + + $standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + self::$standard = $standard; + + // On-the-fly adjust the ruleset test file to be able to test + // sniffs included with relative paths. + $contents = file_get_contents($standard); + self::$contents = $contents; + + $repoRootDir = basename(dirname(dirname(dirname(__DIR__)))); + + $newPath = $repoRootDir; + if (DIRECTORY_SEPARATOR === '\\') { + $newPath = str_replace('\\', '/', $repoRootDir); + } + + $adjusted = str_replace('%path_root_dir%', $newPath, $contents); + + if (file_put_contents($standard, $adjusted) === false) { + self::markTestSkipped('On the fly ruleset adjustment failed'); + } + + $config = new Config(["--standard=$standard"]); + self::$ruleset = new Ruleset($config); + + }//end setUpBeforeClass() + + + /** + * Reset ruleset file. + * + * @return void + */ + public function tearDown() + { + file_put_contents(self::$standard, self::$contents); + + }//end tearDown() + + + /** + * Test that sniffs are registered. + * + * @return void + */ + public function testHasSniffCodes() + { + $this->assertObjectHasAttribute('sniffCodes', self::$ruleset); + $this->assertCount(14, self::$ruleset->sniffCodes); + + }//end testHasSniffCodes() + + + /** + * Test that sniffs are correctly registered, independently on the syntax used to include the sniff. + * + * @param string $key Expected array key. + * @param string $value Expected array value. + * + * @dataProvider dataRegisteredSniffCodes + * + * @return void + */ + public function testRegisteredSniffCodes($key, $value) + { + $this->assertArrayHasKey($key, self::$ruleset->sniffCodes); + $this->assertSame($value, self::$ruleset->sniffCodes[$key]); + + }//end testRegisteredSniffCodes() + + + /** + * Data provider. + * + * @see self::testRegisteredSniffCodes() + * + * @return array + */ + public function dataRegisteredSniffCodes() + { + return [ + [ + 'PSR1.Classes.ClassDeclaration', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff', + ], + [ + 'PSR1.Files.SideEffects', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff', + ], + [ + 'PSR1.Methods.CamelCapsMethodName', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff', + ], + [ + 'Generic.PHP.DisallowAlternativePHPTags', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowAlternativePHPTagsSniff', + ], + [ + 'Generic.PHP.DisallowShortOpenTag', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowShortOpenTagSniff', + ], + [ + 'Generic.Files.ByteOrderMark', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff', + ], + [ + 'Squiz.Classes.ValidClassName', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff', + ], + [ + 'Generic.NamingConventions.UpperCaseConstantName', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\UpperCaseConstantNameSniff', + ], + [ + 'Zend.NamingConventions.ValidVariableName', + 'PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions\ValidVariableNameSniff', + ], + [ + 'Generic.Arrays.ArrayIndent', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff', + ], + [ + 'Generic.Metrics.CyclomaticComplexity', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff', + ], + [ + 'Generic.Files.LineLength', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff', + ], + [ + 'Generic.NamingConventions.CamelCapsFunctionName', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', + ], + [ + 'Generic.Metrics.NestingLevel', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + ], + ]; + + }//end dataRegisteredSniffCodes() + + + /** + * Test that setting properties for standards, categories, sniffs works for all supported rule + * inclusion methods. + * + * @param string $sniffClass The name of the sniff class. + * @param string $propertyName The name of the changed property. + * @param mixed $expectedValue The value expected for the property. + * + * @dataProvider dataSettingProperties + * + * @return void + */ + public function testSettingProperties($sniffClass, $propertyName, $expectedValue) + { + $this->assertObjectHasAttribute('sniffs', self::$ruleset); + $this->assertArrayHasKey($sniffClass, self::$ruleset->sniffs); + $this->assertObjectHasAttribute($propertyName, self::$ruleset->sniffs[$sniffClass]); + + $actualValue = self::$ruleset->sniffs[$sniffClass]->$propertyName; + $this->assertSame($expectedValue, $actualValue); + + }//end testSettingProperties() + + + /** + * Data provider. + * + * @see self::testSettingProperties() + * + * @return array + */ + public function dataSettingProperties() + { + return [ + 'ClassDeclarationSniff' => [ + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff', + 'setforallsniffs', + true, + ], + 'SideEffectsSniff' => [ + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff', + 'setforallsniffs', + true, + ], + 'ValidVariableNameSniff' => [ + 'PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions\ValidVariableNameSniff', + 'setforallincategory', + true, + ], + 'ArrayIndentSniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff', + 'indent', + '2', + ], + 'LineLengthSniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff', + 'lineLimit', + '10', + ], + 'CamelCapsFunctionNameSniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', + 'strict', + false, + ], + 'NestingLevelSniff-nestingLevel' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + 'nestingLevel', + '2', + ], + 'NestingLevelSniff-setforsniffsinincludedruleset' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + 'setforsniffsinincludedruleset', + true, + ], + + // Testing that setting a property at error code level does *not* work. + 'CyclomaticComplexitySniff' => [ + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff', + 'complexity', + 10, + ], + ]; + + }//end dataSettingProperties() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml new file mode 100644 index 000000000..06ce040e7 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc new file mode 100644 index 000000000..488229589 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc @@ -0,0 +1,51 @@ +1,'2'=>2,'3'=>3]; + +/* testMissingKeys */ +$foo = ['1'=>1,2,'3'=>3]; + +/* testMultiTokenKeys */ +$paths = array( + Init::ROOT_DIR.'/a' => 'a', + Init::ROOT_DIR.'/b' => 'b', +); + +/* testMissingKeysCoalesceTernary */ +return [ + $a => static function () { return [1,2,3]; }, + $b ?? $c, + $d ? [$e] : [$f], +]; + +/* testTernaryValues */ +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), +]; + +/* testHeredocValues */ +$foo = array( + << '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', +); diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php new file mode 100644 index 000000000..20c28d60b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php @@ -0,0 +1,290 @@ + + * @copyright 2006-2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Sniffs; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class AbstractArraySniffTest extends AbstractMethodUnitTest +{ + + /** + * The sniff objects we are testing. + * + * This extends the \PHP_CodeSniffer\Sniffs\AbstractArraySniff class to make the + * internal workings of the sniff observable. + * + * @var \PHP_CodeSniffer\Sniffs\AbstractArraySniffTestable + */ + protected static $sniff; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @return void + */ + public static function setUpBeforeClass() + { + self::$sniff = new AbstractArraySniffTestable(); + parent::setUpBeforeClass(); + + }//end setUpBeforeClass() + + + /** + * Test an array of simple values only. + * + * @return void + */ + public function testSimpleValues() + { + $token = $this->getTargetToken('/* testSimpleValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => ['value_start' => ($token + 1)], + 1 => ['value_start' => ($token + 3)], + 2 => ['value_start' => ($token + 5)], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testSimpleValues() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testSimpleKeyValues() + { + $token = $this->getTargetToken('/* testSimpleKeyValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 1), + 'index_end' => ($token + 1), + 'arrow' => ($token + 2), + 'value_start' => ($token + 3), + ], + 1 => [ + 'index_start' => ($token + 5), + 'index_end' => ($token + 5), + 'arrow' => ($token + 6), + 'value_start' => ($token + 7), + ], + 2 => [ + 'index_start' => ($token + 9), + 'index_end' => ($token + 9), + 'arrow' => ($token + 10), + 'value_start' => ($token + 11), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testSimpleKeyValues() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testMissingKeys() + { + $token = $this->getTargetToken('/* testMissingKeys */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 1), + 'index_end' => ($token + 1), + 'arrow' => ($token + 2), + 'value_start' => ($token + 3), + ], + 1 => [ + 'value_start' => ($token + 5), + ], + 2 => [ + 'index_start' => ($token + 7), + 'index_end' => ($token + 7), + 'arrow' => ($token + 8), + 'value_start' => ($token + 9), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMissingKeys() + + + /** + * Test an array with keys that span multiple tokens. + * + * @return void + */ + public function testMultiTokenKeys() + { + $token = $this->getTargetToken('/* testMultiTokenKeys */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 4), + 'index_end' => ($token + 8), + 'arrow' => ($token + 10), + 'value_start' => ($token + 12), + ], + 1 => [ + 'index_start' => ($token + 16), + 'index_end' => ($token + 20), + 'arrow' => ($token + 22), + 'value_start' => ($token + 24), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMultiTokenKeys() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testMissingKeysCoalesceTernary() + { + $token = $this->getTargetToken('/* testMissingKeysCoalesceTernary */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 3), + 'index_end' => ($token + 3), + 'arrow' => ($token + 5), + 'value_start' => ($token + 7), + ], + 1 => [ + 'value_start' => ($token + 31), + ], + 2 => [ + 'value_start' => ($token + 39), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMissingKeysCoalesceTernary() + + + /** + * Test an array of ternary values. + * + * @return void + */ + public function testTernaryValues() + { + $token = $this->getTargetToken('/* testTernaryValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 3), + 'index_end' => ($token + 3), + 'arrow' => ($token + 5), + 'value_start' => ($token + 7), + ], + 1 => [ + 'index_start' => ($token + 32), + 'index_end' => ($token + 32), + 'arrow' => ($token + 34), + 'value_start' => ($token + 36), + ], + 2 => [ + 'index_start' => ($token + 72), + 'index_end' => ($token + 72), + 'arrow' => ($token + 74), + 'value_start' => ($token + 76), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testTernaryValues() + + + /** + * Test an array of heredocs. + * + * @return void + */ + public function testHeredocValues() + { + $token = $this->getTargetToken('/* testHeredocValues */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'value_start' => ($token + 4), + ], + 1 => [ + 'value_start' => ($token + 10), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testHeredocValues() + + + /** + * Test an array of with an arrow function as a value. + * + * @return void + */ + public function testArrowFunctionValue() + { + $token = $this->getTargetToken('/* testArrowFunctionValue */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 4), + 'index_end' => ($token + 4), + 'arrow' => ($token + 6), + 'value_start' => ($token + 8), + ], + 1 => [ + 'index_start' => ($token + 12), + 'index_end' => ($token + 12), + 'arrow' => ($token + 14), + 'value_start' => ($token + 16), + ], + 2 => [ + 'index_start' => ($token + 34), + 'index_end' => ($token + 34), + 'arrow' => ($token + 36), + 'value_start' => ($token + 38), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testArrowFunctionValue() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php new file mode 100644 index 000000000..a224012f2 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Sniffs; + +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; + +class AbstractArraySniffTestable extends AbstractArraySniff +{ + + /** + * The array indicies that were found during processing. + * + * @var array + */ + public $indicies = []; + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $this->indicies = $indices; + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $this->indicies = $indices; + + }//end processMultiLineArray() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc new file mode 100644 index 000000000..5867691c6 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AnonClassParenthesisOwnerTest.inc @@ -0,0 +1,19 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class AnonClassParenthesisOwnerTest extends AbstractMethodUnitTest +{ + + + /** + * Test that anonymous class tokens without parenthesis do not get assigned a parenthesis owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassNoParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassNoParentheses($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS); + $this->assertFalse(array_key_exists('parenthesis_owner', $tokens[$anonClass])); + $this->assertFalse(array_key_exists('parenthesis_opener', $tokens[$anonClass])); + $this->assertFalse(array_key_exists('parenthesis_closer', $tokens[$anonClass])); + + }//end testAnonClassNoParentheses() + + + /** + * Test that the next open/close parenthesis after an anonymous class without parenthesis + * do not get assigned the anonymous class as a parenthesis owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassNoParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassNoParenthesesNextOpenClose($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + $function = $this->getTargetToken($testMarker, T_FUNCTION); + + $opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener])); + $this->assertSame($function, $tokens[$opener]['parenthesis_owner']); + + $closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer])); + $this->assertSame($function, $tokens[$closer]['parenthesis_owner']); + + }//end testAnonClassNoParenthesesNextOpenClose() + + + /** + * Data provider. + * + * @see testAnonClassNoParentheses() + * @see testAnonClassNoParenthesesNextOpenClose() + * + * @return array + */ + public function dataAnonClassNoParentheses() + { + return [ + ['/* testNoParentheses */'], + ['/* testNoParenthesesAndEmptyTokens */'], + ]; + + }//end dataAnonClassNoParentheses() + + + /** + * Test that anonymous class tokens with parenthesis get assigned a parenthesis owner, + * opener and closer; and that the opener/closer get the anonymous class assigned as owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassWithParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassWithParentheses($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + $anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS); + $opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS); + $closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$anonClass])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$anonClass])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$anonClass])); + $this->assertSame($anonClass, $tokens[$anonClass]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$anonClass]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$anonClass]['parenthesis_closer']); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$opener])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$opener])); + $this->assertSame($anonClass, $tokens[$opener]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$opener]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$opener]['parenthesis_closer']); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$closer])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$closer])); + $this->assertSame($anonClass, $tokens[$closer]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$closer]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$closer]['parenthesis_closer']); + + }//end testAnonClassWithParentheses() + + + /** + * Data provider. + * + * @see testAnonClassWithParentheses() + * + * @return array + */ + public function dataAnonClassWithParentheses() + { + return [ + ['/* testWithParentheses */'], + ['/* testWithParenthesesAndEmptyTokens */'], + ]; + + }//end dataAnonClassWithParentheses() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc new file mode 100644 index 000000000..ce5c553cf --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.inc @@ -0,0 +1,35 @@ + 10); + +/* testArrayWithComment */ +$var = Array /*comment*/ (1 => 10); + +/* testNestingArray */ +$var = array( + /* testNestedArray */ + array( + 'key' => 'value', + + /* testClosureReturnType */ + 'closure' => function($a) use($global) : Array {}, + ), +); + +/* testFunctionDeclarationParamType */ +function foo(array $a) {} + +/* testFunctionDeclarationReturnType */ +function foo($a) : int|array|null {} + +class Bar { + /* testClassConst */ + const ARRAY = []; + + /* testClassMethod */ + public function array() {} +} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php new file mode 100644 index 000000000..237258a62 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ArrayKeywordTest.php @@ -0,0 +1,170 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class ArrayKeywordTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the array keyword is correctly tokenized as `T_ARRAY`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayKeyword($testMarker, $testContent='array') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (code)'); + $this->assertSame('T_ARRAY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (type)'); + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + + }//end testArrayKeyword() + + + /** + * Data provider. + * + * @see testArrayKeyword() + * + * @return array + */ + public function dataArrayKeyword() + { + return [ + 'empty array' => ['/* testEmptyArray */'], + 'array with space before parenthesis' => ['/* testArrayWithSpace */'], + 'array with comment before parenthesis' => [ + '/* testArrayWithComment */', + 'Array', + ], + 'nested: outer array' => ['/* testNestingArray */'], + 'nested: inner array' => ['/* testNestedArray */'], + ]; + + }//end dataArrayKeyword() + + + /** + * Test that the array keyword when used in a type declaration is correctly tokenized as `T_STRING`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayType + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayType($testMarker, $testContent='array') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testArrayType() + + + /** + * Data provider. + * + * @see testArrayType() + * + * @return array + */ + public function dataArrayType() + { + return [ + 'closure return type' => [ + '/* testClosureReturnType */', + 'Array', + ], + 'function param type' => ['/* testFunctionDeclarationParamType */'], + 'function union return type' => ['/* testFunctionDeclarationReturnType */'], + ]; + + }//end dataArrayType() + + + /** + * Verify that the retokenization of `T_ARRAY` tokens to `T_STRING` is handled correctly + * for tokens with the contents 'array' which aren't in actual fact the array keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testNotArrayKeyword($testMarker, $testContent='array') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotArrayKeyword() + + + /** + * Data provider. + * + * @see testNotArrayKeyword() + * + * @return array + */ + public function dataNotArrayKeyword() + { + return [ + 'class-constant-name' => [ + '/* testClassConst */', + 'ARRAY', + ], + 'class-method-name' => ['/* testClassMethod */'], + ]; + + }//end dataNotArrayKeyword() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc new file mode 100644 index 000000000..e539adf8a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.inc @@ -0,0 +1,90 @@ + 'foobar'])] +function attribute_with_params_on_function_test() {} + +/* testAttributeWithShortClosureParameter */ +#[AttributeWithParams(static fn ($value) => ! $value)] +function attribute_with_short_closure_param_test() {} + +/* testTwoAttributeOnTheSameLine */ +#[CustomAttribute] #[AttributeWithParams('foo')] +function two_attribute_on_same_line_test() {} + +/* testAttributeAndCommentOnTheSameLine */ +#[CustomAttribute] // This is a comment +function attribute_and_line_comment_on_same_line_test() {} + +/* testAttributeGrouping */ +#[CustomAttribute, AttributeWithParams('foo'), AttributeWithParams('foo', bar: ['bar' => 'foobar'])] +function attribute_grouping_test() {} + +/* testAttributeMultiline */ +#[ + CustomAttribute, + AttributeWithParams('foo'), + AttributeWithParams('foo', bar: ['bar' => 'foobar']) +] +function attribute_multiline_test() {} + +/* testAttributeMultilineWithComment */ +#[ + CustomAttribute, // comment + AttributeWithParams(/* another comment */ 'foo'), + AttributeWithParams('foo', bar: ['bar' => 'foobar']) +] +function attribute_multiline_with_comment_test() {} + +/* testSingleAttributeOnParameter */ +function single_attribute_on_parameter_test(#[ParamAttribute] int $param) {} + +/* testMultipleAttributesOnParameter */ +function multiple_attributes_on_parameter_test(#[ParamAttribute, AttributeWithParams(/* another comment */ 'foo')] int $param) {} + +/* testFqcnAttribute */ +#[Boo\QualifiedName, \Foo\FullyQualifiedName('foo')] +function fqcn_attrebute_test() {} + +/* testNestedAttributes */ +#[Boo\QualifiedName(fn (#[AttributeOne('boo')] $value) => (string) $value)] +function nested_attributes_test() {} + +/* testMultilineAttributesOnParameter */ +function multiline_attributes_on_parameter_test(#[ + AttributeWithParams( + 'foo' + ) + ] int $param) {} + +/* testAttributeContainingTextLookingLikeCloseTag */ +#[DeprecationReason('reason: ')] +function attribute_containing_text_looking_like_close_tag() {} + +/* testAttributeContainingMultilineTextLookingLikeCloseTag */ +#[DeprecationReason( + 'reason: ' +)] +function attribute_containing_mulitline_text_looking_like_close_tag() {} + +/* testInvalidAttribute */ +#[ThisIsNotAnAttribute +function invalid_attribute_test() {} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php new file mode 100644 index 000000000..b10a1efb9 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/AttributesTest.php @@ -0,0 +1,659 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class AttributesTest extends AbstractMethodUnitTest +{ + + + /** + * Test that attributes are parsed correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $length The number of tokens between opener and closer. + * @param array $tokenCodes The codes of tokens inside the attributes. + * + * @dataProvider dataAttribute + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttribute($testMarker, $length, $tokenCodes) + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken($testMarker, T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + $length), $closer); + + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $map = array_map( + function ($token) use ($attribute, $length) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), ($length - 1)) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testAttribute() + + + /** + * Data provider. + * + * @see testAttribute() + * + * @return array + */ + public function dataAttribute() + { + return [ + [ + '/* testAttribute */', + 2, + [ T_STRING ], + ], + [ + '/* testAttributeWithParams */', + 7, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_STRING, + T_DOUBLE_COLON, + T_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeWithNamedParam */', + 10, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_STRING, + T_DOUBLE_COLON, + T_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeOnFunction */', + 2, + [ T_STRING ], + ], + [ + '/* testAttributeOnFunctionWithParams */', + 17, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeWithShortClosureParameter */', + 17, + [ + T_STRING, + T_OPEN_PARENTHESIS, + T_STATIC, + T_WHITESPACE, + T_FN, + T_WHITESPACE, + T_OPEN_PARENTHESIS, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_FN_ARROW, + T_WHITESPACE, + T_BOOLEAN_NOT, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeGrouping */', + 26, + [ + T_STRING, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testAttributeMultiline */', + 31, + [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + ], + ], + [ + '/* testFqcnAttribute */', + 13, + [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_NS_SEPARATOR, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + ]; + + }//end dataAttribute() + + + /** + * Test that multiple attributes on the same line are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testTwoAttributesOnTheSameLine() + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testTwoAttributeOnTheSameLine */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_ATTRIBUTE, $tokens[($closer + 2)]['code']); + $this->assertArrayHasKey('attribute_closer', $tokens[($closer + 2)]); + + }//end testTwoAttributesOnTheSameLine() + + + /** + * Test that attribute followed by a line comment is parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttributeAndLineComment() + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testAttributeAndCommentOnTheSameLine */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_COMMENT, $tokens[($closer + 2)]['code']); + + }//end testAttributeAndLineComment() + + + /** + * Test that attribute followed by a line comment is parsed correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $position The token position (starting from T_FUNCTION) of T_ATTRIBUTE token. + * @param int $length The number of tokens between opener and closer. + * @param array $tokenCodes The codes of tokens inside the attributes. + * + * @dataProvider dataAttributeOnParameters + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttributeOnParameters($testMarker, $position, $length, array $tokenCodes) + { + $tokens = self::$phpcsFile->getTokens(); + + $function = $this->getTargetToken($testMarker, T_FUNCTION); + $attribute = ($function + $position); + + $this->assertSame(T_ATTRIBUTE, $tokens[$attribute]['code']); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $this->assertSame(($attribute + $length), $tokens[$attribute]['attribute_closer']); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_STRING, $tokens[($closer + 2)]['code']); + $this->assertSame('int', $tokens[($closer + 2)]['content']); + + $this->assertSame(T_VARIABLE, $tokens[($closer + 4)]['code']); + $this->assertSame('$param', $tokens[($closer + 4)]['content']); + + $map = array_map( + function ($token) use ($attribute, $length) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), ($length - 1)) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testAttributeOnParameters() + + + /** + * Data provider. + * + * @see testAttributeOnParameters() + * + * @return array + */ + public function dataAttributeOnParameters() + { + return [ + [ + '/* testSingleAttributeOnParameter */', + 4, + 2, + [T_STRING], + ], + [ + '/* testMultipleAttributesOnParameter */', + 4, + 10, + [ + T_STRING, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_COMMENT, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + [ + '/* testMultilineAttributesOnParameter */', + 4, + 13, + [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_WHITESPACE, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_WHITESPACE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_WHITESPACE, + ], + ], + ]; + + }//end dataAttributeOnParameters() + + + /** + * Test that an attribute containing text which looks like a PHP close tag is tokenized correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $length The number of tokens between opener and closer. + * @param array $expectedTokensAttribute The codes of tokens inside the attributes. + * @param array $expectedTokensAfter The codes of tokens after the attributes. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @dataProvider dataAttributeOnTextLookingLikeCloseTag + * + * @return void + */ + public function testAttributeContainingTextLookingLikeCloseTag($testMarker, $length, array $expectedTokensAttribute, array $expectedTokensAfter) + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken($testMarker, T_ATTRIBUTE); + + $this->assertSame('T_ATTRIBUTE', $tokens[$attribute]['type']); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + $length), $closer); + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + $this->assertSame('T_ATTRIBUTE_END', $tokens[$closer]['type']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $i = ($attribute + 1); + foreach ($expectedTokensAttribute as $item) { + list($expectedType, $expectedContents) = $item; + $this->assertSame($expectedType, $tokens[$i]['type']); + $this->assertSame($expectedContents, $tokens[$i]['content']); + $this->assertArrayHasKey('attribute_opener', $tokens[$i]); + $this->assertArrayHasKey('attribute_closer', $tokens[$i]); + ++$i; + } + + $i = ($closer + 1); + foreach ($expectedTokensAfter as $expectedCode) { + $this->assertSame($expectedCode, $tokens[$i]['code']); + ++$i; + } + + }//end testAttributeContainingTextLookingLikeCloseTag() + + + /** + * Data provider. + * + * @see dataAttributeOnTextLookingLikeCloseTag() + * + * @return array + */ + public function dataAttributeOnTextLookingLikeCloseTag() + { + return [ + [ + '/* testAttributeContainingTextLookingLikeCloseTag */', + 5, + [ + [ + 'T_STRING', + 'DeprecationReason', + ], + [ + 'T_OPEN_PARENTHESIS', + '(', + ], + [ + 'T_CONSTANT_ENCAPSED_STRING', + "'reason: '", + ], + [ + 'T_CLOSE_PARENTHESIS', + ')', + ], + [ + 'T_ATTRIBUTE_END', + ']', + ], + ], + [ + T_WHITESPACE, + T_FUNCTION, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + ], + [ + '/* testAttributeContainingMultilineTextLookingLikeCloseTag */', + 8, + [ + [ + 'T_STRING', + 'DeprecationReason', + ], + [ + 'T_OPEN_PARENTHESIS', + '(', + ], + [ + 'T_WHITESPACE', + "\n", + ], + [ + 'T_WHITESPACE', + " ", + ], + [ + 'T_CONSTANT_ENCAPSED_STRING', + "'reason: '", + ], + [ + 'T_WHITESPACE', + "\n", + ], + [ + 'T_CLOSE_PARENTHESIS', + ')', + ], + [ + 'T_ATTRIBUTE_END', + ']', + ], + ], + [ + T_WHITESPACE, + T_FUNCTION, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + ], + ]; + + }//end dataAttributeOnTextLookingLikeCloseTag() + + + /** + * Test that invalid attribute (or comment starting with #[ and without ]) are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testInvalidAttribute() + { + $tokens = self::$phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testInvalidAttribute */', T_ATTRIBUTE); + + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + $this->assertNull($tokens[$attribute]['attribute_closer']); + + }//end testInvalidAttribute() + + + /** + * Test that nested attributes are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testNestedAttributes() + { + $tokens = self::$phpcsFile->getTokens(); + $tokenCodes = [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_OPEN_PARENTHESIS, + T_FN, + T_WHITESPACE, + T_OPEN_PARENTHESIS, + T_ATTRIBUTE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_ATTRIBUTE_END, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_FN_ARROW, + T_WHITESPACE, + T_STRING_CAST, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + ]; + + $attribute = $this->getTargetToken('/* testNestedAttributes */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + 24), $closer); + + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $this->assertArrayNotHasKey('nested_attributes', $tokens[$attribute]); + $this->assertArrayHasKey('nested_attributes', $tokens[($attribute + 8)]); + $this->assertSame([$attribute => ($attribute + 24)], $tokens[($attribute + 8)]['nested_attributes']); + + $test = function (array $tokens, $length, $nestedMap) use ($attribute) { + foreach ($tokens as $token) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + $this->assertSame($nestedMap, $token['nested_attributes']); + } + }; + + $test(array_slice($tokens, ($attribute + 1), 7), 24, [$attribute => $attribute + 24]); + $test(array_slice($tokens, ($attribute + 8), 1), 8 + 5, [$attribute => $attribute + 24]); + + // Length here is 8 (nested attribute offset) + 5 (real length). + $test( + array_slice($tokens, ($attribute + 9), 4), + 8 + 5, + [ + $attribute => $attribute + 24, + $attribute + 8 => $attribute + 13, + ] + ); + + $test(array_slice($tokens, ($attribute + 13), 1), 8 + 5, [$attribute => $attribute + 24]); + $test(array_slice($tokens, ($attribute + 14), 10), 24, [$attribute => $attribute + 24]); + + $map = array_map( + static function ($token) { + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), 23) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testNestedAttributes() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc new file mode 100644 index 000000000..82bfe24fd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.inc @@ -0,0 +1,95 @@ +enum = 'foo'; + } +} + +/* testEnumUsedAsFunctionName */ +function enum() +{ +} + +/* testDeclarationContainingComment */ +enum /* comment */ Name +{ + case SOME_CASE; +} + +enum /* testEnumUsedAsEnumName */ Enum +{ +} + +/* testEnumUsedAsNamespaceName */ +namespace Enum; +/* testEnumUsedAsPartOfNamespaceName */ +namespace My\Enum\Collection; +/* testEnumUsedInObjectInitialization */ +$obj = new Enum; +/* testEnumAsFunctionCall */ +$var = enum($a, $b); +/* testEnumAsFunctionCallWithNamespace */ +var = namespace\enum(); +/* testClassConstantFetchWithEnumAsClassName */ +echo Enum::CONSTANT; +/* testClassConstantFetchWithEnumAsConstantName */ +echo ClassName::ENUM; + +/* testParseErrorMissingName */ +enum { + case SOME_CASE; +} + +/* testParseErrorLiveCoding */ +// This must be the last test in the file. +enum diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php new file mode 100644 index 000000000..33cff3a2c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillEnumTest.php @@ -0,0 +1,229 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillEnumTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the "enum" keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * @param int $openerOffset Offset to find expected scope opener. + * @param int $closerOffset Offset to find expected scope closer. + * + * @dataProvider dataEnums + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testEnums($testMarker, $testContent, $openerOffset, $closerOffset) + { + $tokens = self::$phpcsFile->getTokens(); + + $enum = $this->getTargetToken($testMarker, [T_ENUM, T_STRING], $testContent); + + $this->assertSame(T_ENUM, $tokens[$enum]['code']); + $this->assertSame('T_ENUM', $tokens[$enum]['type']); + + $this->assertArrayHasKey('scope_condition', $tokens[$enum]); + $this->assertArrayHasKey('scope_opener', $tokens[$enum]); + $this->assertArrayHasKey('scope_closer', $tokens[$enum]); + + $this->assertSame($enum, $tokens[$enum]['scope_condition']); + + $scopeOpener = $tokens[$enum]['scope_opener']; + $scopeCloser = $tokens[$enum]['scope_closer']; + + $expectedScopeOpener = ($enum + $openerOffset); + $expectedScopeCloser = ($enum + $closerOffset); + + $this->assertSame($expectedScopeOpener, $scopeOpener); + $this->assertArrayHasKey('scope_condition', $tokens[$scopeOpener]); + $this->assertArrayHasKey('scope_opener', $tokens[$scopeOpener]); + $this->assertArrayHasKey('scope_closer', $tokens[$scopeOpener]); + $this->assertSame($enum, $tokens[$scopeOpener]['scope_condition']); + $this->assertSame($scopeOpener, $tokens[$scopeOpener]['scope_opener']); + $this->assertSame($scopeCloser, $tokens[$scopeOpener]['scope_closer']); + + $this->assertSame($expectedScopeCloser, $scopeCloser); + $this->assertArrayHasKey('scope_condition', $tokens[$scopeCloser]); + $this->assertArrayHasKey('scope_opener', $tokens[$scopeCloser]); + $this->assertArrayHasKey('scope_closer', $tokens[$scopeCloser]); + $this->assertSame($enum, $tokens[$scopeCloser]['scope_condition']); + $this->assertSame($scopeOpener, $tokens[$scopeCloser]['scope_opener']); + $this->assertSame($scopeCloser, $tokens[$scopeCloser]['scope_closer']); + + }//end testEnums() + + + /** + * Data provider. + * + * @see testEnums() + * + * @return array + */ + public function dataEnums() + { + return [ + [ + '/* testPureEnum */', + 'enum', + 4, + 12, + ], + [ + '/* testBackedIntEnum */', + 'enum', + 7, + 29, + ], + [ + '/* testBackedStringEnum */', + 'enum', + 8, + 30, + ], + [ + '/* testComplexEnum */', + 'enum', + 11, + 72, + ], + [ + '/* testEnumWithEnumAsClassName */', + 'enum', + 6, + 7, + ], + [ + '/* testEnumIsCaseInsensitive */', + 'EnUm', + 4, + 5, + ], + [ + '/* testDeclarationContainingComment */', + 'enum', + 6, + 14, + ], + ]; + + }//end dataEnums() + + + /** + * Test that "enum" when not used as the keyword is still tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotEnums + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotEnums($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_ENUM, T_STRING], $testContent); + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testNotEnums() + + + /** + * Data provider. + * + * @see testNotEnums() + * + * @return array + */ + public function dataNotEnums() + { + return [ + [ + '/* testEnumAsClassNameAfterEnumKeyword */', + 'Enum', + ], + [ + '/* testEnumUsedAsClassName */', + 'Enum', + ], + [ + '/* testEnumUsedAsClassConstantName */', + 'ENUM', + ], + [ + '/* testEnumUsedAsMethodName */', + 'enum', + ], + [ + '/* testEnumUsedAsPropertyName */', + 'enum', + ], + [ + '/* testEnumUsedAsFunctionName */', + 'enum', + ], + [ + '/* testEnumUsedAsEnumName */', + 'Enum', + ], + [ + '/* testEnumUsedAsNamespaceName */', + 'Enum', + ], + [ + '/* testEnumUsedAsPartOfNamespaceName */', + 'Enum', + ], + [ + '/* testEnumUsedInObjectInitialization */', + 'Enum', + ], + [ + '/* testEnumAsFunctionCall */', + 'enum', + ], + [ + '/* testEnumAsFunctionCallWithNamespace */', + 'enum', + ], + [ + '/* testClassConstantFetchWithEnumAsClassName */', + 'Enum', + ], + [ + '/* testClassConstantFetchWithEnumAsConstantName */', + 'ENUM', + ], + [ + '/* testParseErrorMissingName */', + 'enum', + ], + [ + '/* testParseErrorLiveCoding */', + 'enum', + ], + ]; + + }//end dataNotEnums() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc new file mode 100644 index 000000000..154d48950 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillExplicitOctalNotationTest.inc @@ -0,0 +1,28 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillExplicitOctalNotationTest extends AbstractMethodUnitTest +{ + + + /** + * Test that explicitly-defined octal values are tokenized as a single number and not as a number and a string. + * + * @param string $marker The comment which prefaces the target token in the test file. + * @param string $value The expected content of the token + * @param int|string $nextToken The expected next token. + * @param string $nextContent The expected content of the next token. + * + * @dataProvider dataExplicitOctalNotation + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testExplicitOctalNotation($marker, $value, $nextToken, $nextContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $number = $this->getTargetToken($marker, [T_LNUMBER]); + + $this->assertSame($value, $tokens[$number]['content'], 'Content of integer token does not match expectation'); + + $this->assertSame($nextToken, $tokens[($number + 1)]['code'], 'Next token is not the expected type, but '.$tokens[($number + 1)]['type']); + $this->assertSame($nextContent, $tokens[($number + 1)]['content'], 'Next token did not have the expected contents'); + + }//end testExplicitOctalNotation() + + + /** + * Data provider. + * + * @see testExplicitOctalNotation() + * + * @return array + */ + public function dataExplicitOctalNotation() + { + return [ + [ + 'marker' => '/* testExplicitOctal */', + 'value' => '0o137041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + [ + 'marker' => '/* testExplicitOctalCapitalised */', + 'value' => '0O137041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + [ + 'marker' => '/* testExplicitOctalWithNumericSeparator */', + 'value' => '0o137_041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + [ + 'marker' => '/* testInvalid1 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o_137', + ], + [ + 'marker' => '/* testInvalid2 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'O_41', + ], + [ + 'marker' => '/* testInvalid3 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o91', + ], + [ + 'marker' => '/* testInvalid4 */', + 'value' => '0O2', + 'nextToken' => T_LNUMBER, + 'nextContent' => '82', + ], + [ + 'marker' => '/* testInvalid5 */', + 'value' => '0o2', + 'nextToken' => T_LNUMBER, + 'nextContent' => '8_2', + ], + [ + 'marker' => '/* testInvalid6 */', + 'value' => '0o2', + 'nextToken' => T_STRING, + 'nextContent' => '_82', + ], + ]; + + }//end dataExplicitOctalNotation() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc new file mode 100644 index 000000000..13f165b77 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.inc @@ -0,0 +1,198 @@ + $x + $y; + +/* testMixedCase */ +$fn1 = Fn($x) => $x + $y; + +/* testWhitespace */ +$fn1 = fn ($x) => $x + $y; + +/* testComment */ +$fn1 = fn /* comment here */ ($x) => $x + $y; + +/* testHeredoc */ +$fn1 = fn() => << /* testNestedInner */ fn($y) => $x * $y + $z; + +/* testNestedSharedCloserOuter */ +$foo = foo(fn() => /* testNestedSharedCloserInner */ fn() => bar() === true); + +/* testFunctionCall */ +$extended = fn($c) => $callable($factory($c), $c); + +/* testChainedFunctionCall */ +$result = Collection::from([1, 2]) + ->map(fn($v) => $v * 2) + ->reduce(/* testFunctionArgument */ fn($tmp, $v) => $tmp + $v, 0); + +/* testClosure */ +$extended = fn($c) => $callable(function() { + for ($x = 1; $x < 10; $x++) { + echo $x; + } + + echo 'done'; +}, $c); + +/* testArrayIndex */ +$found = in_array_cb($needle, $haystack, fn($array, $needle) => $array[2] === $needle); + +$result = array_map( + /* testReturnType */ + static fn(int $number) : int => $number + 1, + $numbers +); + +/* testReference */ +fn&($x) => $x; + +/* testGrouped */ +(fn($x) => $x) + $y; + +/* testArrayValue */ +$a = [ + 'a' => fn() => return 1, +]; + +/* testArrayValueNoTrailingComma */ +$a = [ + 'a' => fn() => foo() +]; + +/* testYield */ +$a = fn($x) => yield 'k' => $x; + +/* testNullableNamespace */ +$a = fn(?\DateTime $x) : ?\DateTime => $x; + +/* testNamespaceOperatorInTypes */ +$fn = fn(namespace\Foo $a) : ?namespace\Foo => $a; + +/* testSelfReturnType */ +fn(self $a) : self => $a; + +/* testParentReturnType */ +fn(parent $a) : parent => $a; + +/* testCallableReturnType */ +fn(callable $a) : callable => $a; + +/* testArrayReturnType */ +fn(array $a) : array => $a; + +/* testStaticReturnType */ +fn(array $a) : static => $a; + +/* testUnionParamType */ +$arrowWithUnionParam = fn(int|float $param) : SomeClass => new SomeClass($param); + +/* testUnionReturnType */ +$arrowWithUnionReturn = fn($param) : int|float => $param | 10; + +/* testTernary */ +$fn = fn($a) => $a ? /* testTernaryThen */ fn() : string => 'a' : /* testTernaryElse */ fn() : string => 'b'; + +/* testTernaryWithTypes */ +$fn = fn(int|null $a) : array|null => $a ? null : []; + +function matchInArrow($x) { + /* testWithMatchValue */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + }; +} + +function matchInArrowAndMore($x) { + /* testWithMatchValueAndMore */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + } . 'suffix'; +} + +function arrowFunctionInMatchWithTrailingComma($x) { + return match ($x) { + /* testInMatchNotLastValue */ + 1 => fn($y) => callMe($y), + /* testInMatchLastValueWithTrailingComma */ + default => fn($y) => callThem($y), + }; +} + +function arrowFunctionInMatchNoTrailingComma1($x) { + return match ($x) { + 1 => fn($y) => callMe($y), + /* testInMatchLastValueNoTrailingComma1 */ + default => fn($y) => callThem($y) + }; +} + +function arrowFunctionInMatchNoTrailingComma2($x) { + return match ($x) { + /* testInMatchLastValueNoTrailingComma2 */ + default => fn($y) => 5 * $y + }; +} + +/* testConstantDeclaration */ +const FN = 'a'; + +/* testConstantDeclarationLower */ +const fn = 'a'; + +class Foo { + /* testStaticMethodName */ + public static function fn($param) { + /* testNestedInMethod */ + $fn = fn($c) => $callable($factory($c), $c); + } + + public function foo() { + /* testPropertyAssignment */ + $this->fn = 'a'; + } +} + +$anon = new class() { + /* testAnonClassMethodName */ + protected function fN($param) { + } +} + +/* testNonArrowStaticMethodCall */ +$a = Foo::fn($param); + +/* testNonArrowConstantAccess */ +$a = MyClass::FN; + +/* testNonArrowConstantAccessMixed */ +$a = MyClass::Fn; + +/* testNonArrowObjectMethodCall */ +$a = $obj->fn($param); + +/* testNonArrowObjectMethodCallUpper */ +$a = $obj->FN($param); + +/* testNonArrowNamespacedFunctionCall */ +$a = MyNS\Sub\Fn($param); + +/* testNonArrowNamespaceOperatorFunctionCall */ +$a = namespace\fn($param); + +/* testNonArrowFunctionNameWithUnionTypes */ +function fn(int|float $param) : string|null {} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$fn = fn diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php new file mode 100644 index 000000000..4d0f4c064 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillFnTokenTest.php @@ -0,0 +1,802 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillFnTokenTest extends AbstractMethodUnitTest +{ + + + /** + * Test simple arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSimple() + { + foreach (['/* testStandard */', '/* testMixedCase */'] as $comment) { + $token = $this->getTargetToken($comment, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 12); + } + + }//end testSimple() + + + /** + * Test whitespace inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWhitespace() + { + $token = $this->getTargetToken('/* testWhitespace */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 6, 13); + + }//end testWhitespace() + + + /** + * Test comments inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testComment() + { + $token = $this->getTargetToken('/* testComment */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 15); + + }//end testComment() + + + /** + * Test heredocs inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testHeredoc() + { + $token = $this->getTargetToken('/* testHeredoc */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 9); + + }//end testHeredoc() + + + /** + * Test nested arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedOuter() + { + $token = $this->getTargetToken('/* testNestedOuter */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 25); + + }//end testNestedOuter() + + + /** + * Test nested arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedInner() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testNestedInner */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 5); + $expectedScopeCloser = ($token + 16); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 4), $tokens[$closer]['scope_opener'], 'Closer scope opener is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer is not the semicolon token'); + + }//end testNestedInner() + + + /** + * Test nested arrow functions with a shared closer. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedSharedCloser() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testNestedSharedCloserOuter */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 20); + + $token = $this->getTargetToken('/* testNestedSharedCloserInner */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 4); + $expectedScopeCloser = ($token + 12); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for "inner" arrow function is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for "inner" arrow function is not the TRUE token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for "inner" arrow function is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for "inner" arrow function is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 4), $tokens[$closer]['scope_opener'], 'Closer scope opener for "inner" arrow function is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for "inner" arrow function is not the TRUE token'); + + }//end testNestedSharedCloser() + + + /** + * Test arrow functions that call functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFunctionCall() + { + $token = $this->getTargetToken('/* testFunctionCall */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 17); + + }//end testFunctionCall() + + + /** + * Test arrow functions that are included in chained calls. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testChainedFunctionCall() + { + $token = $this->getTargetToken('/* testChainedFunctionCall */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 12, 'bracket'); + + }//end testChainedFunctionCall() + + + /** + * Test arrow functions that are used as function arguments. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFunctionArgument() + { + $token = $this->getTargetToken('/* testFunctionArgument */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 15, 'comma'); + + }//end testFunctionArgument() + + + /** + * Test arrow functions that use closures. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testClosure() + { + $token = $this->getTargetToken('/* testClosure */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 60, 'comma'); + + }//end testClosure() + + + /** + * Test arrow functions using an array index. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayIndex() + { + $token = $this->getTargetToken('/* testArrayIndex */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 17, 'comma'); + + }//end testArrayIndex() + + + /** + * Test arrow functions with a return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReturnType() + { + $token = $this->getTargetToken('/* testReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18, 'comma'); + + }//end testReturnType() + + + /** + * Test arrow functions that return a reference. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReference() + { + $token = $this->getTargetToken('/* testReference */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 6, 9); + + }//end testReference() + + + /** + * Test arrow functions that are grouped by parenthesis. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testGrouped() + { + $token = $this->getTargetToken('/* testGrouped */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 8); + + }//end testGrouped() + + + /** + * Test arrow functions that are used as array values. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayValue() + { + $token = $this->getTargetToken('/* testArrayValue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 9, 'comma'); + + }//end testArrayValue() + + + /** + * Test arrow functions that are used as array values with no trailing comma. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayValueNoTrailingComma() + { + $token = $this->getTargetToken('/* testArrayValueNoTrailingComma */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 8, 'closing parenthesis'); + + }//end testArrayValueNoTrailingComma() + + + /** + * Test arrow functions that use the yield keyword. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testYield() + { + $token = $this->getTargetToken('/* testYield */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 14); + + }//end testYield() + + + /** + * Test arrow functions that use nullable namespace types. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNullableNamespace() + { + $token = $this->getTargetToken('/* testNullableNamespace */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 18); + + }//end testNullableNamespace() + + + /** + * Test arrow functions that use the namespace operator in the return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNamespaceOperatorInTypes() + { + $token = $this->getTargetToken('/* testNamespaceOperatorInTypes */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 16, 19); + + }//end testNamespaceOperatorInTypes() + + + /** + * Test arrow functions that use self/parent/callable/array/static return types. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testKeywordReturnTypes() + { + $tokens = self::$phpcsFile->getTokens(); + + $testMarkers = [ + 'Self', + 'Parent', + 'Callable', + 'Array', + 'Static', + ]; + + foreach ($testMarkers as $marker) { + $token = $this->getTargetToken('/* test'.$marker.'ReturnType */', T_FN); + $this->backfillHelper($token); + + $expectedScopeOpener = ($token + 11); + $expectedScopeCloser = ($token + 14); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], "Scope opener is not the arrow token (for $marker)"); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], "Scope closer is not the semicolon token(for $marker)"); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], "Opener scope opener is not the arrow token(for $marker)"); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], "Opener scope closer is not the semicolon token(for $marker)"); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], "Closer scope opener is not the arrow token(for $marker)"); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], "Closer scope closer is not the semicolon token(for $marker)"); + } + + }//end testKeywordReturnTypes() + + + /** + * Test arrow function with a union parameter type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionParamType() + { + $token = $this->getTargetToken('/* testUnionParamType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 13, 21); + + }//end testUnionParamType() + + + /** + * Test arrow function with a union return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionReturnType() + { + $token = $this->getTargetToken('/* testUnionReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18); + + }//end testUnionReturnType() + + + /** + * Test arrow functions used in ternary operators. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTernary() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testTernary */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 40); + + $token = $this->getTargetToken('/* testTernaryThen */', T_FN); + $this->backfillHelper($token); + + $expectedScopeOpener = ($token + 8); + $expectedScopeCloser = ($token + 12); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for THEN is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for THEN is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'Closer scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for THEN is not the semicolon token'); + + $token = $this->getTargetToken('/* testTernaryElse */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 8); + $expectedScopeCloser = ($token + 11); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for ELSE is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for ELSE is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for ELSE is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for ELSE is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 24), $tokens[$closer]['scope_opener'], 'Closer scope opener for ELSE is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for ELSE is not the semicolon token'); + + }//end testTernary() + + + /** + * Test typed arrow functions used in ternary operators. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTernaryWithTypes() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testTernaryWithTypes */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 27); + + }//end testTernaryWithTypes() + + + /** + * Test arrow function returning a match control structure. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWithMatchValue() + { + $token = $this->getTargetToken('/* testWithMatchValue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 44); + + }//end testWithMatchValue() + + + /** + * Test arrow function returning a match control structure with something behind it. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWithMatchValueAndMore() + { + $token = $this->getTargetToken('/* testWithMatchValueAndMore */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 48); + + }//end testWithMatchValueAndMore() + + + /** + * Test match control structure returning arrow functions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param string $expectedCloserType The type of token expected for the scope closer. + * @param string $expectedCloserFriendlyName A friendly name for the type of token expected for the scope closer + * to be used in the error message for failing tests. + * + * @dataProvider dataInMatchValue + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testInMatchValue($testMarker, $openerOffset, $closerOffset, $expectedCloserType, $expectedCloserFriendlyName) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, $openerOffset, $closerOffset, $expectedCloserFriendlyName); + + $this->assertSame($expectedCloserType, $tokens[($token + $closerOffset)]['type'], 'Mismatched scope closer type'); + + }//end testInMatchValue() + + + /** + * Data provider. + * + * @see testInMatchValue() + * + * @return array + */ + public function dataInMatchValue() + { + return [ + 'not_last_value' => [ + '/* testInMatchNotLastValue */', + 5, + 11, + 'T_COMMA', + 'comma', + ], + 'last_value_with_trailing_comma' => [ + '/* testInMatchLastValueWithTrailingComma */', + 5, + 11, + 'T_COMMA', + 'comma', + ], + 'last_value_without_trailing_comma_1' => [ + '/* testInMatchLastValueNoTrailingComma1 */', + 5, + 10, + 'T_CLOSE_PARENTHESIS', + 'close parenthesis', + ], + 'last_value_without_trailing_comma_2' => [ + '/* testInMatchLastValueNoTrailingComma2 */', + 5, + 11, + 'T_VARIABLE', + '$y variable', + ], + ]; + + }//end dataInMatchValue() + + + /** + * Test arrow function nested within a method declaration. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedInMethod() + { + $token = $this->getTargetToken('/* testNestedInMethod */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 17); + + }//end testNestedInMethod() + + + /** + * Verify that "fn" keywords which are not arrow functions get tokenized as T_STRING and don't + * have the extra token array indexes. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotAnArrowFunction + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotAnArrowFunction($testMarker, $testContent='fn') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_FN], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotAnArrowFunction() + + + /** + * Data provider. + * + * @see testNotAnArrowFunction() + * + * @return array + */ + public function dataNotAnArrowFunction() + { + return [ + ['/* testFunctionName */'], + [ + '/* testConstantDeclaration */', + 'FN', + ], + [ + '/* testConstantDeclarationLower */', + 'fn', + ], + ['/* testStaticMethodName */'], + ['/* testPropertyAssignment */'], + [ + '/* testAnonClassMethodName */', + 'fN', + ], + ['/* testNonArrowStaticMethodCall */'], + [ + '/* testNonArrowConstantAccess */', + 'FN', + ], + [ + '/* testNonArrowConstantAccessMixed */', + 'Fn', + ], + ['/* testNonArrowObjectMethodCall */'], + [ + '/* testNonArrowObjectMethodCallUpper */', + 'FN', + ], + [ + '/* testNonArrowNamespacedFunctionCall */', + 'Fn', + ], + ['/* testNonArrowNamespaceOperatorFunctionCall */'], + ['/* testNonArrowFunctionNameWithUnionTypes */'], + ['/* testLiveCoding */'], + ]; + + }//end dataNotAnArrowFunction() + + + /** + * Helper function to check that all token keys are correctly set for T_FN tokens. + * + * @param int $token The T_FN token to check. + * @param bool $skipScopeCloserCheck Whether to skip the scope closer check. + * This should be set to "true" when testing nested arrow functions, + * where the "inner" arrow function shares a scope closer with the + * "outer" arrow function, as the 'scope_condition' for the scope closer + * of the "inner" arrow function will point to the "outer" arrow function. + * + * @return void + */ + private function backfillHelper($token, $skipScopeCloserCheck=false) + { + $tokens = self::$phpcsFile->getTokens(); + + $this->assertTrue(array_key_exists('scope_condition', $tokens[$token]), 'Scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$token]), 'Scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$token]), 'Scope closer is not set'); + $this->assertSame($tokens[$token]['scope_condition'], $token, 'Scope condition is not the T_FN token'); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$token]), 'Parenthesis owner is not set'); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$token]), 'Parenthesis opener is not set'); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$token]), 'Parenthesis closer is not set'); + $this->assertSame($tokens[$token]['parenthesis_owner'], $token, 'Parenthesis owner is not the T_FN token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertTrue(array_key_exists('scope_condition', $tokens[$opener]), 'Opener scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$opener]), 'Opener scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$opener]), 'Opener scope closer is not set'); + $this->assertSame($tokens[$opener]['scope_condition'], $token, 'Opener scope condition is not the T_FN token'); + $this->assertSame(T_FN_ARROW, $tokens[$opener]['code'], 'Arrow scope opener not tokenized as T_FN_ARROW (code)'); + $this->assertSame('T_FN_ARROW', $tokens[$opener]['type'], 'Arrow scope opener not tokenized as T_FN_ARROW (type)'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertTrue(array_key_exists('scope_condition', $tokens[$closer]), 'Closer scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$closer]), 'Closer scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$closer]), 'Closer scope closer is not set'); + if ($skipScopeCloserCheck === false) { + $this->assertSame($tokens[$closer]['scope_condition'], $token, 'Closer scope condition is not the T_FN token'); + } + + $opener = $tokens[$token]['parenthesis_opener']; + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener]), 'Opening parenthesis owner is not set'); + $this->assertSame($tokens[$opener]['parenthesis_owner'], $token, 'Opening parenthesis owner is not the T_FN token'); + + $closer = $tokens[$token]['parenthesis_closer']; + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer]), 'Closing parenthesis owner is not set'); + $this->assertSame($tokens[$closer]['parenthesis_owner'], $token, 'Closing parenthesis owner is not the T_FN token'); + + }//end backfillHelper() + + + /** + * Helper function to check that the scope opener/closer positions are correctly set for T_FN tokens. + * + * @param int $token The T_FN token to check. + * @param int $openerOffset The expected offset of the scope opener in relation to + * the fn keyword. + * @param int $closerOffset The expected offset of the scope closer in relation to + * the fn keyword. + * @param string $expectedCloserType Optional. The type of token expected for the scope closer. + * + * @return void + */ + private function scopePositionTestHelper($token, $openerOffset, $closerOffset, $expectedCloserType='semicolon') + { + $tokens = self::$phpcsFile->getTokens(); + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer is not the '.$expectedCloserType.' token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer is not the '.$expectedCloserType.' token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'Closer scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer is not the '.$expectedCloserType.' token'); + + }//end scopePositionTestHelper() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc new file mode 100644 index 000000000..095a4d7df --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.inc @@ -0,0 +1,319 @@ + 'Zero', + 1 => 'One', + 2 => 'Two', + }; +} + +function matchNoTrailingComma($bool) { + /* testMatchNoTrailingComma */ + echo match ($bool) { + true => "true\n", + false => "false\n" + }; +} + +function matchWithDefault($i) { + /* testMatchWithDefault */ + return match ($i) { + 1 => 1, + 2 => 2, + default => 'default', + }; +} + +function matchExpressionInCondition($i) { + /* testMatchExpressionInCondition */ + return match (true) { + $i >= 50 => '50+', + $i >= 40 => '40-50', + $i >= 30 => '30-40', + $i >= 20 => '20-30', + $i >= 10 => '10-20', + default => '0-10', + }; +} + +function matchMultiCase($day) { + /* testMatchMultiCase */ + return match ($day) { + 1, 7 => false, + 2, 3, 4, 5, 6 => true, + }; +} + +function matchMultiCaseTrailingCommaInCase($bool) { + /* testMatchMultiCaseTrailingCommaInCase */ + echo match ($bool) { + false, + 0, + => "false\n", + true, + 1, + => "true\n", + default, + => "not bool\n", + }; +} + +assert((function () { + /* testMatchInClosureNotLowercase */ + Match ('foo') { + 'foo', 'bar' => false, + 'baz' => 'a', + default => 'b', + }; +})()); + +function matchInArrowFunction($x) { + /* testMatchInArrowFunction */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + }; +} + +function arrowFunctionInMatchNoTrailingComma($x) { + /* testArrowFunctionInMatchNoTrailingComma */ + return match ($x) { + 1 => fn($y) => callMe($y), + default => fn($y) => callThem($y) + }; +} + +/* testMatchInFunctionCallParamNotLowercase */ +var_dump(MATCH ( 'foo' ) { + 'foo' => dump_and_return('foo'), + 'bar' => dump_and_return('bar'), +}); + +/* testMatchInMethodCallParam */ +Test::usesValue(match(true) { true => $i }); + +/* testMatchDiscardResult */ +match (1) { + 1 => print "Executed\n", +}; + +/* testMatchWithDuplicateConditionsWithComments */ +echo match /*comment*/ ( $value /*comment*/ ) { + // Comment. + 2, 1 => '2, 1', + 1 => 1, + 3 => 3, + 4 => 4, + 5 => 5, +}; + +/* testNestedMatchOuter */ +$x = match ($y) { + /* testNestedMatchInner */ + default => match ($z) { 1 => 1 }, +}; + +/* testMatchInTernaryCondition */ +$x = match ($test) { 1 => 'a', 2 => 'b' } ? + /* testMatchInTernaryThen */ match ($test) { 1 => 'a', 2 => 'b' } : + /* testMatchInTernaryElse */ match ($notTest) { 3 => 'a', 4 => 'b' }; + +/* testMatchInArrayValue */ +$array = array( + match ($test) { 1 => 'a', 2 => 'b' }, +); + +/* testMatchInArrayKey */ +$array = [ + match ($test) { 1 => 'a', 2 => 'b' } => 'dynamic keys, woho!', +]; + +/* testMatchreturningArray */ +$matcher = match ($x) { + 0 => array( 0 => 1, 'a' => 2, 'b' => 3 ), + 1 => [1, 2, 3], + 2 => array( 1, [1, 2, 3], 2, 3), + 3 => [ 0 => 1, 'a' => array(1, 2, 3), 'b' => 2, 3], +}; + +/* testSwitchContainingMatch */ +switch ($something) { + /* testMatchWithDefaultNestedInSwitchCase1 */ + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + default => 'default', + }; + continue 2; + + /* testMatchWithDefaultNestedInSwitchCase2 */ + case 'bar' ; + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + default => 'default', + }; + + /* testMatchWithDefaultNestedInSwitchDefault */ + default: + echo 'something', match ($i) { + 1 => 1, + default => 'default', + }; + break; +} + +/* testMatchContainingSwitch */ +$x = match ($y) { + 5, 8 => function($z) { + /* testSwitchNestedInMatch1 */ + switch($z) { + case 'a': + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $i = callMe($a, $b); + return 'default1'; + } + }, + default => function($z) { + /* testSwitchNestedInMatch2 */ + switch($z) { + case 'a'; + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default; + $var = [1, 2, 3]; + return 'default2'; + } + } +}; + +/* testMatchNoCases */ +// Intentional fatal error. +$x = match (true) {}; + +/* testMatchMultiDefault */ +// Intentional fatal error. +echo match (1) { + default => 'foo', + 1 => 'bar', + 2 => 'baz', + default => 'qux', +}; + +/* testNoMatchStaticMethodCall */ +$a = Foo::match($param); + +/* testNoMatchClassConstantAccess */ +$a = MyClass::MATCH; + +/* testNoMatchClassConstantArrayAccessMixedCase */ +$a = MyClass::Match[$a]; + +/* testNoMatchMethodCall */ +$a = $obj->match($param); + +/* testNoMatchMethodCallUpper */ +$a = $obj??->MATCH()->chain($param); + +/* testNoMatchPropertyAccess */ +$a = $obj->match; + +/* testNoMatchNamespacedFunctionCall */ +// Intentional fatal error. +$a = MyNS\Sub\match($param); + +/* testNoMatchNamespaceOperatorFunctionCall */ +// Intentional fatal error. +$a = namespace\match($param); + +interface MatchInterface { + /* testNoMatchInterfaceMethodDeclaration */ + public static function match($param); +} + +class MatchClass { + /* testNoMatchClassConstantDeclarationLower */ + const match = 'a'; + + /* testNoMatchClassMethodDeclaration */ + public static function match($param) { + /* testNoMatchPropertyAssignment */ + $this->match = 'a'; + } +} + +/* testNoMatchClassInstantiation */ +$obj = new Match(); + +$anon = new class() { + /* testNoMatchAnonClassMethodDeclaration */ + protected function maTCH($param) { + } +}; + +/* testNoMatchClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Match {} + +/* testNoMatchInterfaceDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +interface Match {} + +/* testNoMatchTraitDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +trait Match {} + +/* testNoMatchConstantDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +const MATCH = '1'; + +/* testNoMatchFunctionDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +function match() {} + +/* testNoMatchNamespaceDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +namespace Match {} + +/* testNoMatchExtendedClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Foo extends Match {} + +/* testNoMatchImplementedClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Bar implements Match {} + +/* testNoMatchInUseStatement */ +// Intentional fatal error in PHP < 8. Match is now a reserved keyword. +use Match\me; + +function brokenMatchNoCurlies($x) { + /* testNoMatchMissingCurlies */ + // Intentional fatal error. New control structure is not supported without curly braces. + return match ($x) + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + ; +} + +function brokenMatchAlternativeSyntax($x) { + /* testNoMatchAlternativeSyntax */ + // Intentional fatal error. Alternative syntax is not supported. + return match ($x) : + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + endmatch; +} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +echo match diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php new file mode 100644 index 000000000..80f909acd --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillMatchTokenTest.php @@ -0,0 +1,529 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class BackfillMatchTokenTest extends AbstractMethodUnitTest +{ + + + /** + * Test tokenization of match expressions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchExpression + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMatchExpression($testMarker, $openerOffset, $closerOffset, $testContent='match') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_MATCH], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH (code)'); + $this->assertSame('T_MATCH', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH (type)'); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + $this->parenthesisTestHelper($token); + + }//end testMatchExpression() + + + /** + * Data provider. + * + * @see testMatchExpression() + * + * @return array + */ + public function dataMatchExpression() + { + return [ + 'simple_match' => [ + '/* testMatchSimple */', + 6, + 33, + ], + 'no_trailing_comma' => [ + '/* testMatchNoTrailingComma */', + 6, + 24, + ], + 'with_default_case' => [ + '/* testMatchWithDefault */', + 6, + 33, + ], + 'expression_in_condition' => [ + '/* testMatchExpressionInCondition */', + 6, + 77, + ], + 'multicase' => [ + '/* testMatchMultiCase */', + 6, + 40, + ], + 'multicase_trailing_comma_in_case' => [ + '/* testMatchMultiCaseTrailingCommaInCase */', + 6, + 47, + ], + 'in_closure_not_lowercase' => [ + '/* testMatchInClosureNotLowercase */', + 6, + 36, + 'Match', + ], + 'in_arrow_function' => [ + '/* testMatchInArrowFunction */', + 5, + 36, + ], + 'arrow_function_in_match_no_trailing_comma' => [ + '/* testArrowFunctionInMatchNoTrailingComma */', + 6, + 44, + ], + 'in_function_call_param_not_lowercase' => [ + '/* testMatchInFunctionCallParamNotLowercase */', + 8, + 32, + 'MATCH', + ], + 'in_method_call_param' => [ + '/* testMatchInMethodCallParam */', + 5, + 13, + ], + 'discard_result' => [ + '/* testMatchDiscardResult */', + 6, + 18, + ], + 'duplicate_conditions_and_comments' => [ + '/* testMatchWithDuplicateConditionsWithComments */', + 12, + 59, + ], + 'nested_match_outer' => [ + '/* testNestedMatchOuter */', + 6, + 33, + ], + 'nested_match_inner' => [ + '/* testNestedMatchInner */', + 6, + 14, + ], + 'ternary_condition' => [ + '/* testMatchInTernaryCondition */', + 6, + 21, + ], + 'ternary_then' => [ + '/* testMatchInTernaryThen */', + 6, + 21, + ], + 'ternary_else' => [ + '/* testMatchInTernaryElse */', + 6, + 21, + ], + 'array_value' => [ + '/* testMatchInArrayValue */', + 6, + 21, + ], + 'array_key' => [ + '/* testMatchInArrayKey */', + 6, + 21, + ], + 'returning_array' => [ + '/* testMatchreturningArray */', + 6, + 125, + ], + 'nested_in_switch_case_1' => [ + '/* testMatchWithDefaultNestedInSwitchCase1 */', + 6, + 25, + ], + 'nested_in_switch_case_2' => [ + '/* testMatchWithDefaultNestedInSwitchCase2 */', + 6, + 25, + ], + 'nested_in_switch_default' => [ + '/* testMatchWithDefaultNestedInSwitchDefault */', + 6, + 25, + ], + 'match_with_nested_switch' => [ + '/* testMatchContainingSwitch */', + 6, + 180, + ], + 'no_cases' => [ + '/* testMatchNoCases */', + 6, + 7, + ], + 'multi_default' => [ + '/* testMatchMultiDefault */', + 6, + 40, + ], + ]; + + }//end dataMatchExpression() + + + /** + * Verify that "match" keywords which are not match control structures get tokenized as T_STRING + * and don't have the extra token array indexes. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotAMatchStructure + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotAMatchStructure($testMarker, $testContent='match') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_MATCH], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + $next = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($token + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set for opener after'); + } + + }//end testNotAMatchStructure() + + + /** + * Data provider. + * + * @see testNotAMatchStructure() + * + * @return array + */ + public function dataNotAMatchStructure() + { + return [ + 'static_method_call' => ['/* testNoMatchStaticMethodCall */'], + 'class_constant_access' => [ + '/* testNoMatchClassConstantAccess */', + 'MATCH', + ], + 'class_constant_array_access' => [ + '/* testNoMatchClassConstantArrayAccessMixedCase */', + 'Match', + ], + 'method_call' => ['/* testNoMatchMethodCall */'], + 'method_call_uppercase' => [ + '/* testNoMatchMethodCallUpper */', + 'MATCH', + ], + 'property_access' => ['/* testNoMatchPropertyAccess */'], + 'namespaced_function_call' => ['/* testNoMatchNamespacedFunctionCall */'], + 'namespace_operator_function_call' => ['/* testNoMatchNamespaceOperatorFunctionCall */'], + 'interface_method_declaration' => ['/* testNoMatchInterfaceMethodDeclaration */'], + 'class_constant_declaration' => ['/* testNoMatchClassConstantDeclarationLower */'], + 'class_method_declaration' => ['/* testNoMatchClassMethodDeclaration */'], + 'property_assigment' => ['/* testNoMatchPropertyAssignment */'], + 'class_instantiation' => [ + '/* testNoMatchClassInstantiation */', + 'Match', + ], + 'anon_class_method_declaration' => [ + '/* testNoMatchAnonClassMethodDeclaration */', + 'maTCH', + ], + 'class_declaration' => [ + '/* testNoMatchClassDeclaration */', + 'Match', + ], + 'interface_declaration' => [ + '/* testNoMatchInterfaceDeclaration */', + 'Match', + ], + 'trait_declaration' => [ + '/* testNoMatchTraitDeclaration */', + 'Match', + ], + 'constant_declaration' => [ + '/* testNoMatchConstantDeclaration */', + 'MATCH', + ], + 'function_declaration' => ['/* testNoMatchFunctionDeclaration */'], + 'namespace_declaration' => [ + '/* testNoMatchNamespaceDeclaration */', + 'Match', + ], + 'class_extends_declaration' => [ + '/* testNoMatchExtendedClassDeclaration */', + 'Match', + ], + 'class_implements_declaration' => [ + '/* testNoMatchImplementedClassDeclaration */', + 'Match', + ], + 'use_statement' => [ + '/* testNoMatchInUseStatement */', + 'Match', + ], + 'unsupported_inline_control_structure' => ['/* testNoMatchMissingCurlies */'], + 'unsupported_alternative_syntax' => ['/* testNoMatchAlternativeSyntax */'], + 'live_coding' => ['/* testLiveCoding */'], + ]; + + }//end dataNotAMatchStructure() + + + /** + * Verify that the tokenization of switch structures is not affected by the backfill. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * + * @dataProvider dataSwitchExpression + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSwitchExpression($testMarker, $openerOffset, $closerOffset) + { + $token = $this->getTargetToken($testMarker, T_SWITCH); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + $this->parenthesisTestHelper($token); + + }//end testSwitchExpression() + + + /** + * Data provider. + * + * @see testSwitchExpression() + * + * @return array + */ + public function dataSwitchExpression() + { + return [ + 'switch_containing_match' => [ + '/* testSwitchContainingMatch */', + 6, + 174, + ], + 'match_containing_switch_1' => [ + '/* testSwitchNestedInMatch1 */', + 5, + 63, + ], + 'match_containing_switch_2' => [ + '/* testSwitchNestedInMatch2 */', + 5, + 63, + ], + ]; + + }//end dataSwitchExpression() + + + /** + * Verify that the tokenization of a switch case/default structure containing a match structure + * or contained *in* a match structure is not affected by the backfill. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * + * @dataProvider dataSwitchCaseVersusMatch + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSwitchCaseVersusMatch($testMarker, $openerOffset, $closerOffset) + { + $token = $this->getTargetToken($testMarker, [T_CASE, T_DEFAULT]); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + + }//end testSwitchCaseVersusMatch() + + + /** + * Data provider. + * + * @see testSwitchCaseVersusMatch() + * + * @return array + */ + public function dataSwitchCaseVersusMatch() + { + return [ + 'switch_with_nested_match_case_1' => [ + '/* testMatchWithDefaultNestedInSwitchCase1 */', + 3, + 55, + ], + 'switch_with_nested_match_case_2' => [ + '/* testMatchWithDefaultNestedInSwitchCase2 */', + 4, + 21, + ], + 'switch_with_nested_match_default_case' => [ + '/* testMatchWithDefaultNestedInSwitchDefault */', + 1, + 38, + ], + 'match_with_nested_switch_case' => [ + '/* testSwitchDefaultNestedInMatchCase */', + 1, + 18, + ], + 'match_with_nested_switch_default_case' => [ + '/* testSwitchDefaultNestedInMatchDefault */', + 1, + 20, + ], + ]; + + }//end dataSwitchCaseVersusMatch() + + + /** + * Helper function to verify that all scope related array indexes for a control structure + * are set correctly. + * + * @param string $token The control structure token to check. + * @param int $openerOffset The expected offset of the scope opener in relation to + * the control structure token. + * @param int $closerOffset The expected offset of the scope closer in relation to + * the control structure token. + * @param bool $skipScopeCloserCheck Whether to skip the scope closer check. + * This should be set to "true" when testing nested arrow functions, + * where the "inner" arrow function shares a scope closer with the + * "outer" arrow function, as the 'scope_condition' for the scope closer + * of the "inner" arrow function will point to the "outer" arrow function. + * + * @return void + */ + private function scopeTestHelper($token, $openerOffset, $closerOffset, $skipScopeCloserCheck=false) + { + $tokens = self::$phpcsFile->getTokens(); + $tokenArray = $tokens[$token]; + $tokenType = $tokenArray['type']; + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame($token, $tokenArray['scope_condition'], 'Scope condition is not the '.$tokenType.' token'); + $this->assertSame($expectedScopeOpener, $tokenArray['scope_opener'], 'Scope opener of the '.$tokenType.' token incorrect'); + $this->assertSame($expectedScopeCloser, $tokenArray['scope_closer'], 'Scope closer of the '.$tokenType.' token incorrect'); + + $opener = $tokenArray['scope_opener']; + $this->assertArrayHasKey('scope_condition', $tokens[$opener], 'Opener scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Opener scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Opener scope closer is not set'); + $this->assertSame($token, $tokens[$opener]['scope_condition'], 'Opener scope condition is not the '.$tokenType.' token'); + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], $tokenType.' opener scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], $tokenType.' opener scope closer token incorrect'); + + $closer = $tokenArray['scope_closer']; + $this->assertArrayHasKey('scope_condition', $tokens[$closer], 'Closer scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Closer scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Closer scope closer is not set'); + if ($skipScopeCloserCheck === false) { + $this->assertSame($token, $tokens[$closer]['scope_condition'], 'Closer scope condition is not the '.$tokenType.' token'); + } + + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], $tokenType.' closer scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], $tokenType.' closer scope closer token incorrect'); + + if (($opener + 1) !== $closer) { + for ($i = ($opener + 1); $i < $closer; $i++) { + $this->assertArrayHasKey( + $token, + $tokens[$i]['conditions'], + $tokenType.' condition not added for token belonging to the '.$tokenType.' structure' + ); + } + } + + }//end scopeTestHelper() + + + /** + * Helper function to verify that all parenthesis related array indexes for a control structure + * token are set correctly. + * + * @param int $token The position of the control structure token. + * + * @return void + */ + private function parenthesisTestHelper($token) + { + $tokens = self::$phpcsFile->getTokens(); + $tokenArray = $tokens[$token]; + $tokenType = $tokenArray['type']; + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + $this->assertSame($token, $tokenArray['parenthesis_owner'], 'Parenthesis owner is not the '.$tokenType.' token'); + + $opener = $tokenArray['parenthesis_opener']; + $this->assertArrayHasKey('parenthesis_owner', $tokens[$opener], 'Opening parenthesis owner is not set'); + $this->assertSame($token, $tokens[$opener]['parenthesis_owner'], 'Opening parenthesis owner is not the '.$tokenType.' token'); + + $closer = $tokenArray['parenthesis_closer']; + $this->assertArrayHasKey('parenthesis_owner', $tokens[$closer], 'Closing parenthesis owner is not set'); + $this->assertSame($token, $tokens[$closer]['parenthesis_owner'], 'Closing parenthesis owner is not the '.$tokenType.' token'); + + }//end parenthesisTestHelper() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc new file mode 100644 index 000000000..d8559705c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc @@ -0,0 +1,94 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillNumericSeparatorTest extends AbstractMethodUnitTest +{ + + + /** + * Test that numbers using numeric separators are tokenized correctly. + * + * @param array $testData The data required for the specific test case. + * + * @dataProvider dataTestBackfill + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testBackfill($testData) + { + $tokens = self::$phpcsFile->getTokens(); + $number = $this->getTargetToken($testData['marker'], [T_LNUMBER, T_DNUMBER]); + + $this->assertSame(constant($testData['type']), $tokens[$number]['code']); + $this->assertSame($testData['type'], $tokens[$number]['type']); + $this->assertSame($testData['value'], $tokens[$number]['content']); + + }//end testBackfill() + + + /** + * Data provider. + * + * @see testBackfill() + * + * @return array + */ + public function dataTestBackfill() + { + $testHexType = 'T_LNUMBER'; + if (PHP_INT_MAX < 0xCAFEF00D) { + $testHexType = 'T_DNUMBER'; + } + + $testHexMultipleType = 'T_LNUMBER'; + if (PHP_INT_MAX < 0x42726F776E) { + $testHexMultipleType = 'T_DNUMBER'; + } + + $testIntMoreThanMaxType = 'T_LNUMBER'; + if (PHP_INT_MAX < 10223372036854775807) { + $testIntMoreThanMaxType = 'T_DNUMBER'; + } + + return [ + [ + [ + 'marker' => '/* testSimpleLNumber */', + 'type' => 'T_LNUMBER', + 'value' => '1_000_000_000', + ], + ], + [ + [ + 'marker' => '/* testSimpleDNumber */', + 'type' => 'T_DNUMBER', + 'value' => '107_925_284.88', + ], + ], + [ + [ + 'marker' => '/* testFloat */', + 'type' => 'T_DNUMBER', + 'value' => '6.674_083e-11', + ], + ], + [ + [ + 'marker' => '/* testFloat2 */', + 'type' => 'T_DNUMBER', + 'value' => '6.674_083e+11', + ], + ], + [ + [ + 'marker' => '/* testFloat3 */', + 'type' => 'T_DNUMBER', + 'value' => '1_2.3_4e1_23', + ], + ], + [ + [ + 'marker' => '/* testHex */', + 'type' => $testHexType, + 'value' => '0xCAFE_F00D', + ], + ], + [ + [ + 'marker' => '/* testHexMultiple */', + 'type' => $testHexMultipleType, + 'value' => '0x42_72_6F_77_6E', + ], + ], + [ + [ + 'marker' => '/* testHexInt */', + 'type' => 'T_LNUMBER', + 'value' => '0x42_72_6F', + ], + ], + [ + [ + 'marker' => '/* testBinary */', + 'type' => 'T_LNUMBER', + 'value' => '0b0101_1111', + ], + ], + [ + [ + 'marker' => '/* testOctal */', + 'type' => 'T_LNUMBER', + 'value' => '0137_041', + ], + ], + [ + [ + 'marker' => '/* testExplicitOctal */', + 'type' => 'T_LNUMBER', + 'value' => '0o137_041', + ], + ], + [ + [ + 'marker' => '/* testExplicitOctalCapitalised */', + 'type' => 'T_LNUMBER', + 'value' => '0O137_041', + ], + ], + [ + [ + 'marker' => '/* testIntMoreThanMax */', + 'type' => $testIntMoreThanMaxType, + 'value' => '10_223_372_036_854_775_807', + ], + ], + ]; + + }//end dataTestBackfill() + + + /** + * Test that numbers using numeric separators which are considered parse errors and/or + * which aren't relevant to the backfill, do not incorrectly trigger the backfill anyway. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedTokens The token type and content of the expected token sequence. + * + * @dataProvider dataNoBackfill + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNoBackfill($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $number = $this->getTargetToken($testMarker, [T_LNUMBER, T_DNUMBER]); + + foreach ($expectedTokens as $key => $expectedToken) { + $i = ($number + $key); + $this->assertSame($expectedToken['code'], $tokens[$i]['code']); + $this->assertSame($expectedToken['content'], $tokens[$i]['content']); + } + + }//end testNoBackfill() + + + /** + * Data provider. + * + * @see testBackfill() + * + * @return array + */ + public function dataNoBackfill() + { + return [ + [ + '/* testInvalid1 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '100', + ], + [ + 'code' => T_STRING, + 'content' => '_', + ], + ], + ], + [ + '/* testInvalid2 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '__1', + ], + ], + ], + [ + '/* testInvalid3 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '_', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.0', + ], + ], + ], + [ + '/* testInvalid4 */', + [ + [ + 'code' => T_DNUMBER, + 'content' => '1.', + ], + [ + 'code' => T_STRING, + 'content' => '_0', + ], + ], + ], + [ + '/* testInvalid5 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'x_123', + ], + ], + ], + [ + '/* testInvalid6 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'b_101', + ], + ], + ], + [ + '/* testInvalid7 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '_e2', + ], + ], + ], + [ + '/* testInvalid8 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => 'e_2', + ], + ], + ], + [ + '/* testInvalid9 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '107_925_284', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.88', + ], + ], + ], + [ + '/* testInvalid10 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '107_925_284', + ], + [ + 'code' => T_COMMENT, + 'content' => '/*comment*/', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.88', + ], + ], + ], + [ + '/* testInvalid11 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'o_137', + ], + ], + ], + [ + '/* testInvalid12 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'O_41', + ], + ], + ], + [ + '/* testCalc1 */', + [ + [ + 'code' => T_LNUMBER, + 'content' => '667_083', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_MINUS, + 'content' => '-', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_LNUMBER, + 'content' => '11', + ], + ], + ], + [ + '/* test Calc2 */', + [ + [ + 'code' => T_DNUMBER, + 'content' => '6.674_08e3', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_PLUS, + 'content' => '+', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_LNUMBER, + 'content' => '11', + ], + ], + ], + ]; + + }//end dataNoBackfill() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc new file mode 100644 index 000000000..eaf0b4b3c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.inc @@ -0,0 +1,100 @@ +readonly = 'foo'; + + /* testReadonlyPropertyInTernaryOperator */ + $isReadonly = $this->readonly ? true : false; + } +} + +/* testReadonlyUsedAsFunctionName */ +function readonly() +{ +} + +/* testReadonlyUsedAsNamespaceName */ +namespace Readonly; +/* testReadonlyUsedAsPartOfNamespaceName */ +namespace My\Readonly\Collection; +/* testReadonlyAsFunctionCall */ +$var = readonly($a, $b); +/* testClassConstantFetchWithReadonlyAsConstantName */ +echo ClassName::READONLY; + +/* testReadonlyUsedAsFunctionCallWithSpaceBetweenKeywordAndParens */ +$var = readonly /* comment */ (); + +/* testParseErrorLiveCoding */ +// This must be the last test in the file. +readonly diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php new file mode 100644 index 000000000..dddc18ebc --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BackfillReadonlyTest.php @@ -0,0 +1,236 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BackfillReadonlyTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the "readonly" keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataReadonly + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReadonly($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_READONLY, T_STRING], $testContent); + $this->assertSame(T_READONLY, $tokens[$target]['code']); + $this->assertSame('T_READONLY', $tokens[$target]['type']); + + }//end testReadonly() + + + /** + * Data provider. + * + * @see testReadonly() + * + * @return array + */ + public function dataReadonly() + { + return [ + [ + '/* testReadonlyProperty */', + 'readonly', + ], + [ + '/* testVarReadonlyProperty */', + 'readonly', + ], + [ + '/* testReadonlyVarProperty */', + 'readonly', + ], + [ + '/* testStaticReadonlyProperty */', + 'readonly', + ], + [ + '/* testReadonlyStaticProperty */', + 'readonly', + ], + [ + '/* testConstReadonlyProperty */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithoutType */', + 'readonly', + ], + [ + '/* testPublicReadonlyProperty */', + 'readonly', + ], + [ + '/* testProtectedReadonlyProperty */', + 'readonly', + ], + [ + '/* testPrivateReadonlyProperty */', + 'readonly', + ], + [ + '/* testPublicReadonlyPropertyWithReadonlyFirst */', + 'readonly', + ], + [ + '/* testProtectedReadonlyPropertyWithReadonlyFirst */', + 'readonly', + ], + [ + '/* testPrivateReadonlyPropertyWithReadonlyFirst */', + 'readonly', + ], + [ + '/* testReadonlyWithCommentsInDeclaration */', + 'readonly', + ], + [ + '/* testReadonlyWithNullableProperty */', + 'readonly', + ], + [ + '/* testReadonlyNullablePropertyWithUnionTypeHintAndNullFirst */', + 'readonly', + ], + [ + '/* testReadonlyNullablePropertyWithUnionTypeHintAndNullLast */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithArrayTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithSelfTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithParentTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyPropertyWithFullyQualifiedTypeHint */', + 'readonly', + ], + [ + '/* testReadonlyIsCaseInsensitive */', + 'ReAdOnLy', + ], + [ + '/* testReadonlyConstructorPropertyPromotion */', + 'readonly', + ], + [ + '/* testReadonlyConstructorPropertyPromotionWithReference */', + 'ReadOnly', + ], + [ + '/* testReadonlyPropertyInAnonymousClass */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsFunctionCallWithSpaceBetweenKeywordAndParens */', + 'readonly', + ], + [ + '/* testParseErrorLiveCoding */', + 'readonly', + ], + ]; + + }//end dataReadonly() + + + /** + * Test that "readonly" when not used as the keyword is still tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotReadonly + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotReadonly($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_READONLY, T_STRING], $testContent); + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testNotReadonly() + + + /** + * Data provider. + * + * @see testNotReadonly() + * + * @return array + */ + public function dataNotReadonly() + { + return [ + [ + '/* testReadonlyUsedAsClassConstantName */', + 'READONLY', + ], + [ + '/* testReadonlyUsedAsMethodName */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsPropertyName */', + 'readonly', + ], + [ + '/* testReadonlyPropertyInTernaryOperator */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsFunctionName */', + 'readonly', + ], + [ + '/* testReadonlyUsedAsNamespaceName */', + 'Readonly', + ], + [ + '/* testReadonlyUsedAsPartOfNamespaceName */', + 'Readonly', + ], + [ + '/* testReadonlyAsFunctionCall */', + 'readonly', + ], + [ + '/* testClassConstantFetchWithReadonlyAsConstantName */', + 'READONLY', + ], + ]; + + }//end dataNotReadonly() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc new file mode 100644 index 000000000..bfdbdc18c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.inc @@ -0,0 +1,134 @@ + $param | $int; + +/* testTypeUnionArrowReturnType */ +$arrowWithReturnType = fn ($param) : int|null => $param * 10; + +/* testBitwiseOrInArrayKey */ +$array = array( + A | B => /* testBitwiseOrInArrayValue */ B | C +); + +/* testBitwiseOrInShortArrayKey */ +$array = [ + A | B => /* testBitwiseOrInShortArrayValue */ B | C +]; + +/* testBitwiseOrTryCatch */ +try { +} catch ( ExceptionA | ExceptionB $e ) { +} + +/* testBitwiseOrNonArrowFnFunctionCall */ +$obj->fn($something | $else); + +/* testTypeUnionNonArrowFunctionDeclaration */ +function &fn(int|false $something) {} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +return function( type| diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php new file mode 100644 index 000000000..d56e7340a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/BitwiseOrTest.php @@ -0,0 +1,138 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class BitwiseOrTest extends AbstractMethodUnitTest +{ + + + /** + * Test that non-union type bitwise or tokens are still tokenized as bitwise or. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataBitwiseOr + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBitwiseOr($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION]); + $this->assertSame(T_BITWISE_OR, $tokens[$opener]['code']); + $this->assertSame('T_BITWISE_OR', $tokens[$opener]['type']); + + }//end testBitwiseOr() + + + /** + * Data provider. + * + * @see testBitwiseOr() + * + * @return array + */ + public function dataBitwiseOr() + { + return [ + ['/* testBitwiseOr1 */'], + ['/* testBitwiseOr2 */'], + ['/* testBitwiseOrPropertyDefaultValue */'], + ['/* testBitwiseOrParamDefaultValue */'], + ['/* testBitwiseOr3 */'], + ['/* testBitwiseOrClosureParamDefault */'], + ['/* testBitwiseOrArrowParamDefault */'], + ['/* testBitwiseOrArrowExpression */'], + ['/* testBitwiseOrInArrayKey */'], + ['/* testBitwiseOrInArrayValue */'], + ['/* testBitwiseOrInShortArrayKey */'], + ['/* testBitwiseOrInShortArrayValue */'], + ['/* testBitwiseOrTryCatch */'], + ['/* testBitwiseOrNonArrowFnFunctionCall */'], + ['/* testLiveCoding */'], + ]; + + }//end dataBitwiseOr() + + + /** + * Test that bitwise or tokens when used as part of a union type are tokenized as `T_TYPE_UNION`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataTypeUnion + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypeUnion($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION]); + $this->assertSame(T_TYPE_UNION, $tokens[$opener]['code']); + $this->assertSame('T_TYPE_UNION', $tokens[$opener]['type']); + + }//end testTypeUnion() + + + /** + * Data provider. + * + * @see testTypeUnion() + * + * @return array + */ + public function dataTypeUnion() + { + return [ + ['/* testTypeUnionPropertySimple */'], + ['/* testTypeUnionPropertyReverseModifierOrder */'], + ['/* testTypeUnionPropertyMulti1 */'], + ['/* testTypeUnionPropertyMulti2 */'], + ['/* testTypeUnionPropertyMulti3 */'], + ['/* testTypeUnionPropertyNamespaceRelative */'], + ['/* testTypeUnionPropertyPartiallyQualified */'], + ['/* testTypeUnionPropertyFullyQualified */'], + ['/* testTypeUnionPropertyWithReadOnlyKeyword */'], + ['/* testTypeUnionPropertyWithReadOnlyKeywordFirst */'], + ['/* testTypeUnionPropertyWithStaticAndReadOnlyKeywords */'], + ['/* testTypeUnionPropertyWithVarAndReadOnlyKeywords */'], + ['/* testTypeUnionPropertyWithOnlyReadOnlyKeyword */'], + ['/* testTypeUnionParam1 */'], + ['/* testTypeUnionParam2 */'], + ['/* testTypeUnionParam3 */'], + ['/* testTypeUnionParamNamespaceRelative */'], + ['/* testTypeUnionParamPartiallyQualified */'], + ['/* testTypeUnionParamFullyQualified */'], + ['/* testTypeUnionReturnType */'], + ['/* testTypeUnionConstructorPropertyPromotion */'], + ['/* testTypeUnionAbstractMethodReturnType1 */'], + ['/* testTypeUnionAbstractMethodReturnType2 */'], + ['/* testTypeUnionReturnTypeNamespaceRelative */'], + ['/* testTypeUnionReturnPartiallyQualified */'], + ['/* testTypeUnionReturnFullyQualified */'], + ['/* testTypeUnionClosureParamIllegalNullable */'], + ['/* testTypeUnionWithReference */'], + ['/* testTypeUnionWithSpreadOperator */'], + ['/* testTypeUnionClosureReturn */'], + ['/* testTypeUnionArrowParam */'], + ['/* testTypeUnionArrowReturnType */'], + ['/* testTypeUnionNonArrowFunctionDeclaration */'], + ]; + + }//end dataTypeUnion() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc new file mode 100644 index 000000000..e3c10ad8e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.inc @@ -0,0 +1,227 @@ + 'a', + 2 => 'b', + /* testMatchDefaultIsKeyword */ default => 'default', +}; + +$closure = /* testFnIsKeyword */ fn () => 'string'; + +function () { + /* testYieldIsKeyword */ yield $f; + /* testYieldFromIsKeyword */ yield from someFunction(); +}; + +/* testDeclareIsKeyword */ declare(ticks=1): +/* testEndDeclareIsKeyword */ enddeclare; + +if (true /* testAndIsKeyword */ and false /* testOrIsKeyword */ or null /* testXorIsKeyword */ xor 0) { + +} + +$anonymousClass = new /* testAnonymousClassIsKeyword */ class {}; +$anonymousClass2 = new class /* testExtendsInAnonymousClassIsKeyword */ extends SomeParent {}; +$anonymousClass3 = new class /* testImplementsInAnonymousClassIsKeyword */ implements SomeInterface {}; + +$instantiated1 = new /* testClassInstantiationParentIsKeyword */ parent(); +$instantiated2 = new /* testClassInstantiationSelfIsKeyword */ SELF; +$instantiated3 = new /* testClassInstantiationStaticIsKeyword */ static($param); + +class Foo extends /* testNamespaceInNameIsKeyword */ namespace\Exception +{} + +function /* testKeywordAfterFunctionShouldBeString */ eval() {} +function /* testKeywordAfterFunctionByRefShouldBeString */ &switch() {} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php new file mode 100644 index 000000000..a747e573c --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ContextSensitiveKeywordsTest.php @@ -0,0 +1,509 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class ContextSensitiveKeywordsTest extends AbstractMethodUnitTest +{ + + + /** + * Test that context sensitive keyword is tokenized as string when it should be string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataStrings + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testStrings($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, (Tokens::$contextSensitiveKeywords + [T_STRING])); + + $this->assertSame(T_STRING, $tokens[$token]['code']); + $this->assertSame('T_STRING', $tokens[$token]['type']); + + }//end testStrings() + + + /** + * Data provider. + * + * @see testStrings() + * + * @return array + */ + public function dataStrings() + { + return [ + ['/* testAbstract */'], + ['/* testArray */'], + ['/* testAs */'], + ['/* testBreak */'], + ['/* testCallable */'], + ['/* testCase */'], + ['/* testCatch */'], + ['/* testClass */'], + ['/* testClone */'], + ['/* testConst */'], + ['/* testContinue */'], + ['/* testDeclare */'], + ['/* testDefault */'], + ['/* testDo */'], + ['/* testEcho */'], + ['/* testElse */'], + ['/* testElseIf */'], + ['/* testEmpty */'], + ['/* testEndDeclare */'], + ['/* testEndFor */'], + ['/* testEndForeach */'], + ['/* testEndIf */'], + ['/* testEndSwitch */'], + ['/* testEndWhile */'], + ['/* testEnum */'], + ['/* testEval */'], + ['/* testExit */'], + ['/* testExtends */'], + ['/* testFinal */'], + ['/* testFinally */'], + ['/* testFn */'], + ['/* testFor */'], + ['/* testForeach */'], + ['/* testFunction */'], + ['/* testGlobal */'], + ['/* testGoto */'], + ['/* testIf */'], + ['/* testImplements */'], + ['/* testInclude */'], + ['/* testIncludeOnce */'], + ['/* testInstanceOf */'], + ['/* testInsteadOf */'], + ['/* testInterface */'], + ['/* testIsset */'], + ['/* testList */'], + ['/* testMatch */'], + ['/* testNamespace */'], + ['/* testNew */'], + ['/* testParent */'], + ['/* testPrint */'], + ['/* testPrivate */'], + ['/* testProtected */'], + ['/* testPublic */'], + ['/* testReadonly */'], + ['/* testRequire */'], + ['/* testRequireOnce */'], + ['/* testReturn */'], + ['/* testSelf */'], + ['/* testStatic */'], + ['/* testSwitch */'], + ['/* testThrows */'], + ['/* testTrait */'], + ['/* testTry */'], + ['/* testUnset */'], + ['/* testUse */'], + ['/* testVar */'], + ['/* testWhile */'], + ['/* testYield */'], + ['/* testYieldFrom */'], + ['/* testAnd */'], + ['/* testOr */'], + ['/* testXor */'], + + ['/* testKeywordAfterNamespaceShouldBeString */'], + ['/* testNamespaceNameIsString1 */'], + ['/* testNamespaceNameIsString2 */'], + ['/* testNamespaceNameIsString3 */'], + + ['/* testKeywordAfterFunctionShouldBeString */'], + ['/* testKeywordAfterFunctionByRefShouldBeString */'], + ]; + + }//end dataStrings() + + + /** + * Test that context sensitive keyword is tokenized as keyword when it should be keyword. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedTokenType The expected token type. + * + * @dataProvider dataKeywords + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testKeywords($testMarker, $expectedTokenType) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, (Tokens::$contextSensitiveKeywords + [T_ANON_CLASS, T_MATCH_DEFAULT, T_PARENT, T_SELF, T_STRING])); + + $this->assertSame(constant($expectedTokenType), $tokens[$token]['code']); + $this->assertSame($expectedTokenType, $tokens[$token]['type']); + + }//end testKeywords() + + + /** + * Data provider. + * + * @see testKeywords() + * + * @return array + */ + public function dataKeywords() + { + return [ + [ + '/* testNamespaceIsKeyword */', + 'T_NAMESPACE', + ], + [ + '/* testAbstractIsKeyword */', + 'T_ABSTRACT', + ], + [ + '/* testClassIsKeyword */', + 'T_CLASS', + ], + [ + '/* testExtendsIsKeyword */', + 'T_EXTENDS', + ], + [ + '/* testImplementsIsKeyword */', + 'T_IMPLEMENTS', + ], + [ + '/* testUseIsKeyword */', + 'T_USE', + ], + [ + '/* testInsteadOfIsKeyword */', + 'T_INSTEADOF', + ], + [ + '/* testAsIsKeyword */', + 'T_AS', + ], + [ + '/* testConstIsKeyword */', + 'T_CONST', + ], + [ + '/* testPrivateIsKeyword */', + 'T_PRIVATE', + ], + [ + '/* testProtectedIsKeyword */', + 'T_PROTECTED', + ], + [ + '/* testPublicIsKeyword */', + 'T_PUBLIC', + ], + [ + '/* testVarIsKeyword */', + 'T_VAR', + ], + [ + '/* testStaticIsKeyword */', + 'T_STATIC', + ], + [ + '/* testReadonlyIsKeyword */', + 'T_READONLY', + ], + [ + '/* testFinalIsKeyword */', + 'T_FINAL', + ], + [ + '/* testFunctionIsKeyword */', + 'T_FUNCTION', + ], + [ + '/* testCallableIsKeyword */', + 'T_CALLABLE', + ], + [ + '/* testSelfIsKeyword */', + 'T_SELF', + ], + [ + '/* testParentIsKeyword */', + 'T_PARENT', + ], + [ + '/* testReturnIsKeyword */', + 'T_RETURN', + ], + + [ + '/* testInterfaceIsKeyword */', + 'T_INTERFACE', + ], + [ + '/* testTraitIsKeyword */', + 'T_TRAIT', + ], + [ + '/* testEnumIsKeyword */', + 'T_ENUM', + ], + + [ + '/* testNewIsKeyword */', + 'T_NEW', + ], + [ + '/* testInstanceOfIsKeyword */', + 'T_INSTANCEOF', + ], + [ + '/* testCloneIsKeyword */', + 'T_CLONE', + ], + + [ + '/* testIfIsKeyword */', + 'T_IF', + ], + [ + '/* testEmptyIsKeyword */', + 'T_EMPTY', + ], + [ + '/* testElseIfIsKeyword */', + 'T_ELSEIF', + ], + [ + '/* testElseIsKeyword */', + 'T_ELSE', + ], + [ + '/* testEndIfIsKeyword */', + 'T_ENDIF', + ], + + [ + '/* testForIsKeyword */', + 'T_FOR', + ], + [ + '/* testEndForIsKeyword */', + 'T_ENDFOR', + ], + + [ + '/* testForeachIsKeyword */', + 'T_FOREACH', + ], + [ + '/* testEndForeachIsKeyword */', + 'T_ENDFOREACH', + ], + + [ + '/* testSwitchIsKeyword */', + 'T_SWITCH', + ], + [ + '/* testCaseIsKeyword */', + 'T_CASE', + ], + [ + '/* testDefaultIsKeyword */', + 'T_DEFAULT', + ], + [ + '/* testEndSwitchIsKeyword */', + 'T_ENDSWITCH', + ], + [ + '/* testBreakIsKeyword */', + 'T_BREAK', + ], + [ + '/* testContinueIsKeyword */', + 'T_CONTINUE', + ], + + [ + '/* testDoIsKeyword */', + 'T_DO', + ], + [ + '/* testWhileIsKeyword */', + 'T_WHILE', + ], + [ + '/* testEndWhileIsKeyword */', + 'T_ENDWHILE', + ], + + [ + '/* testTryIsKeyword */', + 'T_TRY', + ], + [ + '/* testThrowIsKeyword */', + 'T_THROW', + ], + [ + '/* testCatchIsKeyword */', + 'T_CATCH', + ], + [ + '/* testFinallyIsKeyword */', + 'T_FINALLY', + ], + + [ + '/* testGlobalIsKeyword */', + 'T_GLOBAL', + ], + [ + '/* testEchoIsKeyword */', + 'T_ECHO', + ], + [ + '/* testPrintIsKeyword */', + 'T_PRINT', + ], + [ + '/* testDieIsKeyword */', + 'T_EXIT', + ], + [ + '/* testEvalIsKeyword */', + 'T_EVAL', + ], + [ + '/* testExitIsKeyword */', + 'T_EXIT', + ], + [ + '/* testIssetIsKeyword */', + 'T_ISSET', + ], + [ + '/* testUnsetIsKeyword */', + 'T_UNSET', + ], + + [ + '/* testIncludeIsKeyword */', + 'T_INCLUDE', + ], + [ + '/* testIncludeOnceIsKeyword */', + 'T_INCLUDE_ONCE', + ], + [ + '/* testRequireIsKeyword */', + 'T_REQUIRE', + ], + [ + '/* testRequireOnceIsKeyword */', + 'T_REQUIRE_ONCE', + ], + + [ + '/* testListIsKeyword */', + 'T_LIST', + ], + [ + '/* testGotoIsKeyword */', + 'T_GOTO', + ], + [ + '/* testMatchIsKeyword */', + 'T_MATCH', + ], + [ + '/* testMatchDefaultIsKeyword */', + 'T_MATCH_DEFAULT', + ], + [ + '/* testFnIsKeyword */', + 'T_FN', + ], + + [ + '/* testYieldIsKeyword */', + 'T_YIELD', + ], + [ + '/* testYieldFromIsKeyword */', + 'T_YIELD_FROM', + ], + + [ + '/* testDeclareIsKeyword */', + 'T_DECLARE', + ], + [ + '/* testEndDeclareIsKeyword */', + 'T_ENDDECLARE', + ], + + [ + '/* testAndIsKeyword */', + 'T_LOGICAL_AND', + ], + [ + '/* testOrIsKeyword */', + 'T_LOGICAL_OR', + ], + [ + '/* testXorIsKeyword */', + 'T_LOGICAL_XOR', + ], + + [ + '/* testAnonymousClassIsKeyword */', + 'T_ANON_CLASS', + ], + [ + '/* testExtendsInAnonymousClassIsKeyword */', + 'T_EXTENDS', + ], + [ + '/* testImplementsInAnonymousClassIsKeyword */', + 'T_IMPLEMENTS', + ], + [ + '/* testClassInstantiationParentIsKeyword */', + 'T_PARENT', + ], + [ + '/* testClassInstantiationSelfIsKeyword */', + 'T_SELF', + ], + [ + '/* testClassInstantiationStaticIsKeyword */', + 'T_STATIC', + ], + [ + '/* testNamespaceInNameIsKeyword */', + 'T_NAMESPACE', + ], + ]; + + }//end dataKeywords() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc new file mode 100644 index 000000000..648149d2f --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.inc @@ -0,0 +1,203 @@ + 1, + 2 => 2, + /* testSimpleMatchDefault */ + default => 'default', + }; +} + +function switchWithDefault($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefault */ + default: + return 'default'; + } +} + +function switchWithDefaultAndCurlies($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefaultWithCurlies */ + default: { + return 'default'; + } + } +} + +function matchWithDefaultInSwitch() { + switch ($something) { + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase1 */ + default => 'default', + }; + continue; + + case 'bar' : + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase2 */ + default => 'default', + }; + + /* testSwitchDefault */ + default; + echo 'something', match ($i) { + 1, => 1, + /* testMatchDefaultNestedInSwitchDefault */ + default, => 'default', + }; + break; + } +} + +function switchWithDefaultInMatch() { + $x = match ($y) { + 5, 8 => function($z) { + switch($z) { + case 'a'; + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $var = [1, 2, 3]; + return 'default1'; + } + }, + /* testMatchDefault */ + default => function($z) { + switch($z) { + case 'a': + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default: + $i = callMe($a, $b); + return 'default2'; + } + } + }; +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testClassConstantAsShortArrayKey */ + SomeClass::DEFAULT => 1, + /* testClassPropertyAsShortArrayKey */ + SomeClass->DEFAULT => 1, + /* testNamespacedConstantAsShortArrayKey */ + // Intentional parse error PHP < 8.0. Reserved keyword used as namespaced constant. + SomeNamespace\DEFAULT => 1, + /* testFQNGlobalConstantAsShortArrayKey */ + // Intentional parse error in PHP < 8.0. Reserved keyword used as global constant. + \DEFAULT => 1, + ]; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testClassConstantAsLongArrayKey */ + SomeClass::DEFAULT => 1, + ); +} + +function yieldWithConstantKey() { + /* testClassConstantAsYieldKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKey */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ), + }, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKey */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ], + }, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testClassConstantAsLongArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInLongArray */ + DEFAULT => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testClassConstantAsShortArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInShortArray */ + DEFAULT => 'foo' + }, + ]; +} + +function switchWithConstantNonDefault($i) { + switch ($i) { + /* testClassConstantInSwitchCase */ + case SomeClass::DEFAULT: + return 1; + + /* testClassPropertyInSwitchCase */ + case SomeClass->DEFAULT: + return 2; + + /* testNamespacedConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as constant. + case SomeNamespace\DEFAULT: + return 2; + + /* testNamespaceRelativeConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as global constant. + case namespace\DEFAULT: + return 2; + } +} + +class Foo { + /* testClassConstant */ + const DEFAULT = 'foo'; + + /* testMethodDeclaration */ + public function default() {} +} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php new file mode 100644 index 000000000..9a5b061a0 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DefaultKeywordTest.php @@ -0,0 +1,302 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class DefaultKeywordTest extends AbstractMethodUnitTest +{ + + + /** + * Test the retokenization of the `default` keyword for match structure to `T_MATCH_DEFAULT`. + * + * Note: Cases and default structures within a match structure do *NOT* get case/default scope + * conditions, in contrast to case and default structures in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchDefault + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testMatchDefault($testMarker, $testContent='default') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)'); + $this->assertSame('T_MATCH_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testMatchDefault() + + + /** + * Data provider. + * + * @see testMatchDefault() + * + * @return array + */ + public function dataMatchDefault() + { + return [ + 'simple_match_default' => ['/* testSimpleMatchDefault */'], + 'match_default_in_switch_case_1' => ['/* testMatchDefaultNestedInSwitchCase1 */'], + 'match_default_in_switch_case_2' => ['/* testMatchDefaultNestedInSwitchCase2 */'], + 'match_default_in_switch_default' => ['/* testMatchDefaultNestedInSwitchDefault */'], + 'match_default_containing_switch' => ['/* testMatchDefault */'], + + 'match_default_with_nested_long_array_and_default_key' => [ + '/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */', + 'DEFAULT', + ], + 'match_default_with_nested_long_array_and_default_key_2' => [ + '/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */', + 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key' => [ + '/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */', + 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key_2' => [ + '/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */', + 'DEFAULT', + ], + 'match_default_in_long_array' => [ + '/* testMatchDefaultNestedInLongArray */', + 'DEFAULT', + ], + 'match_default_in_short_array' => [ + '/* testMatchDefaultNestedInShortArray */', + 'DEFAULT', + ], + ]; + + }//end dataMatchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_DEFAULT` tokens in switch control structures. + * + * Note: Cases and default structures within a switch control structure *do* get case/default scope + * conditions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param int|null $conditionStop The expected offset at which tokens stop having T_DEFAULT as a scope condition. + * @param string $testContent The token content to look for. + * + * @dataProvider dataSwitchDefault + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testSwitchDefault($testMarker, $openerOffset, $closerOffset, $conditionStop=null, $testContent='default') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertSame(T_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (code)'); + $this->assertSame('T_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (type)'); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame($token, $tokenArray['scope_condition'], 'Scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokenArray['scope_opener'], 'Scope opener of the T_DEFAULT token incorrect'); + $this->assertSame($expectedScopeCloser, $tokenArray['scope_closer'], 'Scope closer of the T_DEFAULT token incorrect'); + + $opener = $tokenArray['scope_opener']; + $this->assertArrayHasKey('scope_condition', $tokens[$opener], 'Opener scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Opener scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Opener scope closer is not set'); + $this->assertSame($token, $tokens[$opener]['scope_condition'], 'Opener scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'T_DEFAULT opener scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'T_DEFAULT opener scope closer token incorrect'); + + $closer = $tokenArray['scope_closer']; + $this->assertArrayHasKey('scope_condition', $tokens[$closer], 'Closer scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Closer scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Closer scope closer is not set'); + $this->assertSame($token, $tokens[$closer]['scope_condition'], 'Closer scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'T_DEFAULT closer scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'T_DEFAULT closer scope closer token incorrect'); + + if (($opener + 1) !== $closer) { + $end = $closer; + if (isset($conditionStop) === true) { + $end = $conditionStop; + } + + for ($i = ($opener + 1); $i < $end; $i++) { + $this->assertArrayHasKey( + $token, + $tokens[$i]['conditions'], + 'T_DEFAULT condition not added for token belonging to the T_DEFAULT structure' + ); + } + } + + }//end testSwitchDefault() + + + /** + * Data provider. + * + * @see testSwitchDefault() + * + * @return array + */ + public function dataSwitchDefault() + { + return [ + 'simple_switch_default' => [ + '/* testSimpleSwitchDefault */', + 1, + 4, + ], + 'simple_switch_default_with_curlies' => [ + // For a default structure with curly braces, the scope opener + // will be the open curly and the closer the close curly. + // However, scope conditions will not be set for open to close, + // but only for the open token up to the "break/return/continue" etc. + '/* testSimpleSwitchDefaultWithCurlies */', + 3, + 12, + 6, + ], + 'switch_default_toplevel' => [ + '/* testSwitchDefault */', + 1, + 43, + ], + 'switch_default_nested_in_match_case' => [ + '/* testSwitchDefaultNestedInMatchCase */', + 1, + 20, + ], + 'switch_default_nested_in_match_default' => [ + '/* testSwitchDefaultNestedInMatchDefault */', + 1, + 18, + ], + ]; + + }//end dataSwitchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_STRING` tokens with the contents 'default' which aren't in + * actual fact the default keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotDefaultKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT') + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testNotDefaultKeyword() + + + /** + * Data provider. + * + * @see testNotDefaultKeyword() + * + * @return array + */ + public function dataNotDefaultKeyword() + { + return [ + 'class-constant-as-short-array-key' => ['/* testClassConstantAsShortArrayKey */'], + 'class-property-as-short-array-key' => ['/* testClassPropertyAsShortArrayKey */'], + 'namespaced-constant-as-short-array-key' => ['/* testNamespacedConstantAsShortArrayKey */'], + 'fqn-global-constant-as-short-array-key' => ['/* testFQNGlobalConstantAsShortArrayKey */'], + 'class-constant-as-long-array-key' => ['/* testClassConstantAsLongArrayKey */'], + 'class-constant-as-yield-key' => ['/* testClassConstantAsYieldKey */'], + + 'class-constant-as-long-array-key-nested-in-match' => ['/* testClassConstantAsLongArrayKeyNestedInMatch */'], + 'class-constant-as-long-array-key-nested-in-match-2' => ['/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */'], + 'class-constant-as-short-array-key-nested-in-match' => ['/* testClassConstantAsShortArrayKeyNestedInMatch */'], + 'class-constant-as-short-array-key-nested-in-match-2' => ['/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */'], + 'class-constant-as-long-array-key-with-nested-match' => ['/* testClassConstantAsLongArrayKeyWithNestedMatch */'], + 'class-constant-as-short-array-key-with-nested-match' => ['/* testClassConstantAsShortArrayKeyWithNestedMatch */'], + + 'class-constant-in-switch-case' => ['/* testClassConstantInSwitchCase */'], + 'class-property-in-switch-case' => ['/* testClassPropertyInSwitchCase */'], + 'namespaced-constant-in-switch-case' => ['/* testNamespacedConstantInSwitchCase */'], + 'namespace-relative-constant-in-switch-case' => ['/* testNamespaceRelativeConstantInSwitchCase */'], + + 'class-constant-declaration' => ['/* testClassConstant */'], + 'class-method-declaration' => [ + '/* testMethodDeclaration */', + 'default', + ], + ]; + + }//end dataNotDefaultKeyword() + + + /** + * Test a specific edge case where a scope opener would be incorrectly set. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/3326 + * + * @return void + */ + public function testIssue3326() + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testClassConstant */', [T_SEMICOLON]); + $tokenArray = $tokens[$token]; + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testIssue3326() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc new file mode 100644 index 000000000..b67b06601 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.inc @@ -0,0 +1,281 @@ + 'Zero', + ); +} + +function simpleShortArray($x) { + return [ + /* testShortArrayArrowSimple */ + 0 => 'Zero', + ]; +} + +function simpleLongList($x) { + list( + /* testLongListArrowSimple */ + 0 => $a, + ) = $x; +} + +function simpleShortList($x) { + [ + /* testShortListArrowSimple */ + 0 => $a, + ] = $x; +} + +function simpleYield($x) { + $i = 0; + foreach (explode("\n", $x) as $line) { + /* testYieldArrowSimple */ + yield ++$i => $line; + } +} + +function simpleForeach($x) { + /* testForeachArrowSimple */ + foreach ($x as $k => $value) {} +} + +function simpleMatch($x) { + return match ($x) { + /* testMatchArrowSimpleSingleCase */ + 0 => 'Zero', + /* testMatchArrowSimpleMultiCase */ + 2, 4, 6 => 'Zero', + /* testMatchArrowSimpleSingleCaseWithTrailingComma */ + 1, => 'Zero', + /* testMatchArrowSimpleMultiCaseWithTrailingComma */ + 3, 5, => 'Zero', + }; +} + +function simpleArrowFunction($y) { + /* testFnArrowSimple */ + return fn ($y) => callMe($y); +} + +function matchNestedInMatch() { + $x = match ($y) { + /* testMatchArrowNestedMatchOuter */ + default, => match ($z) { + /* testMatchArrowNestedMatchInner */ + 1 => 1 + }, + }; +} + +function matchNestedInLongArrayValue() { + $array = array( + /* testLongArrayArrowWithNestedMatchValue1 */ + 'a' => match ($test) { + /* testMatchArrowInLongArrayValue1 */ + 1 => 'a', + /* testMatchArrowInLongArrayValue2 */ + 2 => 'b' + }, + /* testLongArrayArrowWithNestedMatchValue2 */ + $i => match ($test) { + /* testMatchArrowInLongArrayValue3 */ + 1 => 'a', + }, + ); +} + +function matchNestedInShortArrayValue() { + $array = [ + /* testShortArrayArrowWithNestedMatchValue1 */ + 'a' => match ($test) { + /* testMatchArrowInShortArrayValue1 */ + 1 => 'a', + /* testMatchArrowInShortArrayValue2 */ + 2 => 'b' + }, + /* testShortArrayArrowWithNestedMatchValue2 */ + $i => match ($test) { + /* testMatchArrowInShortArrayValue3 */ + 1 => 'a', + }, + ]; +} + +function matchNestedInLongArrayKey() { + $array = array( + match ($test) { /* testMatchArrowInLongArrayKey1 */ 1 => 'a', /* testMatchArrowInLongArrayKey2 */ 2 => 'b' } + /* testLongArrayArrowWithMatchKey */ + => 'dynamic keys, woho!', + ); +} + +function matchNestedInShortArrayKey() { + $array = [ + match ($test) { /* testMatchArrowInShortArrayKey1 */ 1 => 'a', /* testMatchArrowInShortArrayKey2 */ 2 => 'b' } + /* testShortArrayArrowWithMatchKey */ + => 'dynamic keys, woho!', + ]; +} + +function arraysNestedInMatch() { + $matcher = match ($x) { + /* testMatchArrowWithLongArrayBodyWithKeys */ + 0 => array( + /* testLongArrayArrowInMatchBody1 */ + 0 => 1, + /* testLongArrayArrowInMatchBody2 */ + 'a' => 2, + /* testLongArrayArrowInMatchBody3 */ + 'b' => 3 + ), + /* testMatchArrowWithShortArrayBodyWithoutKeys */ + 1 => [1, 2, 3], + /* testMatchArrowWithLongArrayBodyWithoutKeys */ + 2 => array( 1, [1, 2, 3], 2, 3), + /* testMatchArrowWithShortArrayBodyWithKeys */ + 3 => [ + /* testShortArrayArrowInMatchBody1 */ + 0 => 1, + /* testShortArrayArrowInMatchBody2 */ + 'a' => array(1, 2, 3), + /* testShortArrayArrowInMatchBody3 */ + 'b' => 2, + 3 + ], + /* testShortArrayArrowinMatchCase1 */ + [4 => 'a', /* testShortArrayArrowinMatchCase2 */ 5 => 6] + /* testMatchArrowWithShortArrayWithKeysAsCase */ + => 'match with array as case value', + /* testShortArrayArrowinMatchCase3 */ + [4 => 'a'], /* testLongArrayArrowinMatchCase4 */ array(5 => 6), + /* testMatchArrowWithMultipleArraysWithKeysAsCase */ + => 'match with multiple arrays as case value', + }; +} + +function matchNestedInArrowFunction($x) { + /* testFnArrowWithMatchInValue */ + $fn = fn($x) => match(true) { + /* testMatchArrowInFnBody1 */ + 1, 2, 3, 4, 5 => 'foo', + /* testMatchArrowInFnBody2 */ + default => 'bar', + }; +} + +function arrowFunctionsNestedInMatch($x) { + return match ($x) { + /* testMatchArrowWithFnBody1 */ + 1 => /* testFnArrowInMatchBody1 */ fn($y) => callMe($y), + /* testMatchArrowWithFnBody2 */ + default => /* testFnArrowInMatchBody2 */ fn($y) => callThem($y) + }; +} + +function matchShortArrayMismash() { + $array = [ + match ($test) { + /* testMatchArrowInComplexShortArrayKey1 */ + 1 => [ /* testShortArrayArrowInComplexMatchValueinShortArrayKey */ 1 => 'a'], + /* testMatchArrowInComplexShortArrayKey2 */ + 2 => 'b' + /* testShortArrayArrowInComplexMatchArrayMismash */ + } => match ($test) { + /* testMatchArrowInComplexShortArrayValue1 */ + 1 => [ /* testShortArrayArrowInComplexMatchValueinShortArrayValue */ 1 => 'a'], + /* testMatchArrowInComplexShortArrayValue2 */ + 2 => /* testFnArrowInComplexMatchValueInShortArrayValue */ fn($y) => callMe($y) + }, + ]; +} + + +function longListInMatch($x, $y) { + return match($x) { + /* testMatchArrowWithLongListBody */ + 1 => list('a' => $a, /* testLongListArrowInMatchBody */ 'b' => $b, 'c' => list('d' => $c)) = $y, + /* testLongListArrowInMatchCase */ + list('a' => $a, 'b' => $b) = $y /* testMatchArrowWithLongListInCase */ => 'something' + }; +} + +function shortListInMatch($x, $y) { + return match($x) { + /* testMatchArrowWithShortListBody */ + 1 => ['a' => $a, 'b' => $b, 'c' => /* testShortListArrowInMatchBody */ ['d' => $c]] = $y, + /* testShortListArrowInMatchCase */ + ['a' => $a, 'b' => $b] = $y /* testMatchArrowWithShortListInCase */ => 'something' + }; +} + +function matchInLongList() { + /* testMatchArrowInLongListKey */ + list(match($x) {1 => 1, 2 => 2} /* testLongListArrowWithMatchInKey */ => $a) = $array; +} + +function matchInShortList() { + /* testMatchArrowInShortListKey */ + [match($x) {1 => 1, 2 => 2} /* testShortListArrowWithMatchInKey */ => $a] = $array; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testLongArrayArrowWithClassConstantKey */ + SomeClass::DEFAULT => 1, + ); +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testShortArrayArrowWithClassConstantKey */ + SomeClass::DEFAULT => 1, + ]; +} + +function yieldWithConstantKey() { + /* testYieldArrowWithClassConstantKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchArrowWithNestedLongArrayWithClassConstantKey */ + default => array( + /* testLongArrayArrowWithClassConstantKeyNestedInMatch */ + SomeClass::DEFAULT => 1, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchArrowWithNestedShortArrayWithClassConstantKey */ + default => [ + /* testShortArrayArrowWithClassConstantKeyNestedInMatch */ + SomeClass::DEFAULT => 1, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testLongArrayArrowWithClassConstantKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchArrowNestedInLongArrayWithClassConstantKey */ + default => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testShortArrayArrowWithClassConstantKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchArrowNestedInShortArrayWithClassConstantKey */ + default => 'foo' + }, + ]; +} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php new file mode 100644 index 000000000..ad1a411ff --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleArrowTest.php @@ -0,0 +1,237 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class DoubleArrowTest extends AbstractMethodUnitTest +{ + + + /** + * Test that "normal" double arrows are correctly tokenized as `T_DOUBLE_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataDoubleArrow + * @coversNothing + * + * @return void + */ + public function testDoubleArrow($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_DOUBLE_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DOUBLE_ARROW (code)'); + $this->assertSame('T_DOUBLE_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DOUBLE_ARROW (type)'); + + }//end testDoubleArrow() + + + /** + * Data provider. + * + * @see testDoubleArrow() + * + * @return array + */ + public function dataDoubleArrow() + { + return [ + 'simple_long_array' => ['/* testLongArrayArrowSimple */'], + 'simple_short_array' => ['/* testShortArrayArrowSimple */'], + 'simple_long_list' => ['/* testLongListArrowSimple */'], + 'simple_short_list' => ['/* testShortListArrowSimple */'], + 'simple_yield' => ['/* testYieldArrowSimple */'], + 'simple_foreach' => ['/* testForeachArrowSimple */'], + + 'long_array_with_match_value_1' => ['/* testLongArrayArrowWithNestedMatchValue1 */'], + 'long_array_with_match_value_2' => ['/* testLongArrayArrowWithNestedMatchValue2 */'], + 'short_array_with_match_value_1' => ['/* testShortArrayArrowWithNestedMatchValue1 */'], + 'short_array_with_match_value_2' => ['/* testShortArrayArrowWithNestedMatchValue2 */'], + + 'long_array_with_match_key' => ['/* testLongArrayArrowWithMatchKey */'], + 'short_array_with_match_key' => ['/* testShortArrayArrowWithMatchKey */'], + + 'long_array_in_match_body_1' => ['/* testLongArrayArrowInMatchBody1 */'], + 'long_array_in_match_body_2' => ['/* testLongArrayArrowInMatchBody2 */'], + 'long_array_in_match_body_3' => ['/* testLongArrayArrowInMatchBody3 */'], + 'short_array_in_match_body_1' => ['/* testShortArrayArrowInMatchBody1 */'], + 'short_array_in_match_body_2' => ['/* testShortArrayArrowInMatchBody2 */'], + 'short_array_in_match_body_3' => ['/* testShortArrayArrowInMatchBody3 */'], + + 'short_array_in_match_case_1' => ['/* testShortArrayArrowinMatchCase1 */'], + 'short_array_in_match_case_2' => ['/* testShortArrayArrowinMatchCase2 */'], + 'short_array_in_match_case_3' => ['/* testShortArrayArrowinMatchCase3 */'], + 'long_array_in_match_case_4' => ['/* testLongArrayArrowinMatchCase4 */'], + + 'in_complex_short_array_key_match_value' => ['/* testShortArrayArrowInComplexMatchValueinShortArrayKey */'], + 'in_complex_short_array_toplevel' => ['/* testShortArrayArrowInComplexMatchArrayMismash */'], + 'in_complex_short_array_value_match_value' => ['/* testShortArrayArrowInComplexMatchValueinShortArrayValue */'], + + 'long_list_in_match_body' => ['/* testLongListArrowInMatchBody */'], + 'long_list_in_match_case' => ['/* testLongListArrowInMatchCase */'], + 'short_list_in_match_body' => ['/* testShortListArrowInMatchBody */'], + 'short_list_in_match_case' => ['/* testShortListArrowInMatchCase */'], + 'long_list_with_match_in_key' => ['/* testLongListArrowWithMatchInKey */'], + 'short_list_with_match_in_key' => ['/* testShortListArrowWithMatchInKey */'], + + 'long_array_with_constant_default_in_key' => ['/* testLongArrayArrowWithClassConstantKey */'], + 'short_array_with_constant_default_in_key' => ['/* testShortArrayArrowWithClassConstantKey */'], + 'yield_with_constant_default_in_key' => ['/* testYieldArrowWithClassConstantKey */'], + + 'long_array_with_default_in_key_in_match' => ['/* testLongArrayArrowWithClassConstantKeyNestedInMatch */'], + 'short_array_with_default_in_key_in_match' => ['/* testShortArrayArrowWithClassConstantKeyNestedInMatch */'], + 'long_array_with_default_in_key_with_match' => ['/* testLongArrayArrowWithClassConstantKeyWithNestedMatch */'], + 'short_array_with_default_in_key_with_match' => ['/* testShortArrayArrowWithClassConstantKeyWithNestedMatch */'], + ]; + + }//end dataDoubleArrow() + + + /** + * Test that double arrows in match expressions which are the demarkation between a case and the return value + * are correctly tokenized as `T_MATCH_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataMatchArrow + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testMatchArrow($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_ARROW (code)'); + $this->assertSame('T_MATCH_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_ARROW (type)'); + + }//end testMatchArrow() + + + /** + * Data provider. + * + * @see testMatchArrow() + * + * @return array + */ + public function dataMatchArrow() + { + return [ + 'single_case' => ['/* testMatchArrowSimpleSingleCase */'], + 'multi_case' => ['/* testMatchArrowSimpleMultiCase */'], + 'single_case_with_trailing_comma' => ['/* testMatchArrowSimpleSingleCaseWithTrailingComma */'], + 'multi_case_with_trailing_comma' => ['/* testMatchArrowSimpleMultiCaseWithTrailingComma */'], + 'match_nested_outer' => ['/* testMatchArrowNestedMatchOuter */'], + 'match_nested_inner' => ['/* testMatchArrowNestedMatchInner */'], + + 'in_long_array_value_1' => ['/* testMatchArrowInLongArrayValue1 */'], + 'in_long_array_value_2' => ['/* testMatchArrowInLongArrayValue2 */'], + 'in_long_array_value_3' => ['/* testMatchArrowInLongArrayValue3 */'], + 'in_short_array_value_1' => ['/* testMatchArrowInShortArrayValue1 */'], + 'in_short_array_value_2' => ['/* testMatchArrowInShortArrayValue2 */'], + 'in_short_array_value_3' => ['/* testMatchArrowInShortArrayValue3 */'], + + 'in_long_array_key_1' => ['/* testMatchArrowInLongArrayKey1 */'], + 'in_long_array_key_2' => ['/* testMatchArrowInLongArrayKey2 */'], + 'in_short_array_key_1' => ['/* testMatchArrowInShortArrayKey1 */'], + 'in_short_array_key_2' => ['/* testMatchArrowInShortArrayKey2 */'], + + 'with_long_array_value_with_keys' => ['/* testMatchArrowWithLongArrayBodyWithKeys */'], + 'with_short_array_value_without_keys' => ['/* testMatchArrowWithShortArrayBodyWithoutKeys */'], + 'with_long_array_value_without_keys' => ['/* testMatchArrowWithLongArrayBodyWithoutKeys */'], + 'with_short_array_value_with_keys' => ['/* testMatchArrowWithShortArrayBodyWithKeys */'], + + 'with_short_array_with_keys_as_case' => ['/* testMatchArrowWithShortArrayWithKeysAsCase */'], + 'with_multiple_arrays_with_keys_as_case' => ['/* testMatchArrowWithMultipleArraysWithKeysAsCase */'], + + 'in_fn_body_case' => ['/* testMatchArrowInFnBody1 */'], + 'in_fn_body_default' => ['/* testMatchArrowInFnBody2 */'], + 'with_fn_body_case' => ['/* testMatchArrowWithFnBody1 */'], + 'with_fn_body_default' => ['/* testMatchArrowWithFnBody2 */'], + + 'in_complex_short_array_key_1' => ['/* testMatchArrowInComplexShortArrayKey1 */'], + 'in_complex_short_array_key_2' => ['/* testMatchArrowInComplexShortArrayKey2 */'], + 'in_complex_short_array_value_1' => ['/* testMatchArrowInComplexShortArrayValue1 */'], + 'in_complex_short_array_value_2' => ['/* testMatchArrowInComplexShortArrayValue2 */'], + + 'with_long_list_in_body' => ['/* testMatchArrowWithLongListBody */'], + 'with_long_list_in_case' => ['/* testMatchArrowWithLongListInCase */'], + 'with_short_list_in_body' => ['/* testMatchArrowWithShortListBody */'], + 'with_short_list_in_case' => ['/* testMatchArrowWithShortListInCase */'], + 'in_long_list_key' => ['/* testMatchArrowInLongListKey */'], + 'in_short_list_key' => ['/* testMatchArrowInShortListKey */'], + + 'with_long_array_value_with_default_key' => ['/* testMatchArrowWithNestedLongArrayWithClassConstantKey */'], + 'with_short_array_value_with_default_key' => ['/* testMatchArrowWithNestedShortArrayWithClassConstantKey */'], + 'in_long_array_value_with_default_key' => ['/* testMatchArrowNestedInLongArrayWithClassConstantKey */'], + 'in_short_array_value_with_default_key' => ['/* testMatchArrowNestedInShortArrayWithClassConstantKey */'], + ]; + + }//end dataMatchArrow() + + + /** + * Test that double arrows used as the scope opener for an arrow function + * are correctly tokenized as `T_FN_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataFnArrow + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFnArrow($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_FN_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_FN_ARROW (code)'); + $this->assertSame('T_FN_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_FN_ARROW (type)'); + + }//end testFnArrow() + + + /** + * Data provider. + * + * @see testFnArrow() + * + * @return array + */ + public function dataFnArrow() + { + return [ + 'simple_fn' => ['/* testFnArrowSimple */'], + + 'with_match_as_value' => ['/* testFnArrowWithMatchInValue */'], + 'in_match_value_case' => ['/* testFnArrowInMatchBody1 */'], + 'in_match_value_default' => ['/* testFnArrowInMatchBody2 */'], + + 'in_complex_match_value_in_short_array' => ['/* testFnArrowInComplexMatchValueInShortArrayValue */'], + ]; + + }//end dataFnArrow() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc new file mode 100644 index 000000000..62535b1e4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.inc @@ -0,0 +1,52 @@ +bar"; +/* testProperty2 */ +"{$foo->bar}"; + +/* testMethod1 */ +"{$foo->bar()}"; + +/* testClosure1 */ +"{$foo()}"; + +/* testChain1 */ +"{$foo['bar']->baz()()}"; + +/* testVariableVar1 */ +"${$bar}"; +/* testVariableVar2 */ +"${(foo)}"; +/* testVariableVar3 */ +"${foo->bar}"; + +/* testNested1 */ +"${foo["${bar}"]}"; +/* testNested2 */ +"${foo["${bar['baz']}"]}"; +/* testNested3 */ +"${foo->{$baz}}"; +/* testNested4 */ +"${foo->{${'a'}}}"; +/* testNested5 */ +"${foo->{"${'a'}"}}"; + +/* testParseError */ +"${foo["${bar diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php new file mode 100644 index 000000000..cc9fe49ec --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/DoubleQuotedStringTest.php @@ -0,0 +1,136 @@ + + * @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class DoubleQuotedStringTest extends AbstractMethodUnitTest +{ + + + /** + * Test that double quoted strings contain the complete string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent The expected content of the double quoted string. + * + * @dataProvider dataDoubleQuotedString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testDoubleQuotedString($testMarker, $expectedContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, T_DOUBLE_QUOTED_STRING); + $this->assertSame($expectedContent, $tokens[$target]['content']); + + }//end testDoubleQuotedString() + + + /** + * Data provider. + * + * @see testDoubleQuotedString() + * + * @return array + */ + public function dataDoubleQuotedString() + { + return [ + [ + 'testMarker' => '/* testSimple1 */', + 'expectedContent' => '"$foo"', + ], + [ + 'testMarker' => '/* testSimple2 */', + 'expectedContent' => '"{$foo}"', + ], + [ + 'testMarker' => '/* testSimple3 */', + 'expectedContent' => '"${foo}"', + ], + [ + 'testMarker' => '/* testDIM1 */', + 'expectedContent' => '"$foo[bar]"', + ], + [ + 'testMarker' => '/* testDIM2 */', + 'expectedContent' => '"{$foo[\'bar\']}"', + ], + [ + 'testMarker' => '/* testDIM3 */', + 'expectedContent' => '"${foo[\'bar\']}"', + ], + [ + 'testMarker' => '/* testProperty1 */', + 'expectedContent' => '"$foo->bar"', + ], + [ + 'testMarker' => '/* testProperty2 */', + 'expectedContent' => '"{$foo->bar}"', + ], + [ + 'testMarker' => '/* testMethod1 */', + 'expectedContent' => '"{$foo->bar()}"', + ], + [ + 'testMarker' => '/* testClosure1 */', + 'expectedContent' => '"{$foo()}"', + ], + [ + 'testMarker' => '/* testChain1 */', + 'expectedContent' => '"{$foo[\'bar\']->baz()()}"', + ], + [ + 'testMarker' => '/* testVariableVar1 */', + 'expectedContent' => '"${$bar}"', + ], + [ + 'testMarker' => '/* testVariableVar2 */', + 'expectedContent' => '"${(foo)}"', + ], + [ + 'testMarker' => '/* testVariableVar3 */', + 'expectedContent' => '"${foo->bar}"', + ], + [ + 'testMarker' => '/* testNested1 */', + 'expectedContent' => '"${foo["${bar}"]}"', + ], + [ + 'testMarker' => '/* testNested2 */', + 'expectedContent' => '"${foo["${bar[\'baz\']}"]}"', + ], + [ + 'testMarker' => '/* testNested3 */', + 'expectedContent' => '"${foo->{$baz}}"', + ], + [ + 'testMarker' => '/* testNested4 */', + 'expectedContent' => '"${foo->{${\'a\'}}}"', + ], + [ + 'testMarker' => '/* testNested5 */', + 'expectedContent' => '"${foo->{"${\'a\'}"}}"', + ], + [ + 'testMarker' => '/* testParseError */', + 'expectedContent' => '"${foo["${bar +', + ], + ]; + + }//end dataDoubleQuotedString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc new file mode 100644 index 000000000..13b87242e --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/EnumCaseTest.inc @@ -0,0 +1,95 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class EnumCaseTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the enum "case" is converted to T_ENUM_CASE. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataEnumCases + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testEnumCases($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $enumCase = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + + $this->assertSame(T_ENUM_CASE, $tokens[$enumCase]['code']); + $this->assertSame('T_ENUM_CASE', $tokens[$enumCase]['type']); + + $this->assertArrayNotHasKey('scope_condition', $tokens[$enumCase], 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokens[$enumCase], 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokens[$enumCase], 'Scope closer is set'); + + }//end testEnumCases() + + + /** + * Data provider. + * + * @see testEnumCases() + * + * @return array + */ + public function dataEnumCases() + { + return [ + ['/* testPureEnumCase */'], + ['/* testBackingIntegerEnumCase */'], + ['/* testBackingStringEnumCase */'], + ['/* testEnumCaseInComplexEnum */'], + ['/* testEnumCaseIsCaseInsensitive */'], + ['/* testEnumCaseAfterSwitch */'], + ['/* testEnumCaseAfterSwitchWithEndSwitch */'], + ]; + + }//end dataEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNotEnumCases + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testNotEnumCases($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $case = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + + $this->assertSame(T_CASE, $tokens[$case]['code']); + $this->assertSame('T_CASE', $tokens[$case]['type']); + + $this->assertArrayHasKey('scope_condition', $tokens[$case], 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$case], 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$case], 'Scope closer is not set'); + + }//end testNotEnumCases() + + + /** + * Data provider. + * + * @see testNotEnumCases() + * + * @return array + */ + public function dataNotEnumCases() + { + return [ + ['/* testCaseWithSemicolonIsNotEnumCase */'], + ['/* testCaseWithConstantIsNotEnumCase */'], + ['/* testCaseWithConstantAndIdenticalIsNotEnumCase */'], + ['/* testCaseWithAssigmentToConstantIsNotEnumCase */'], + ['/* testIsNotEnumCaseIsCaseInsensitive */'], + ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], + ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], + ]; + + }//end dataNotEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataKeywordAsEnumCaseNameShouldBeString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testKeywordAsEnumCaseNameShouldBeString($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $enumCaseName = $this->getTargetToken($testMarker, [T_STRING, T_INTERFACE, T_TRAIT, T_ENUM, T_FUNCTION, T_FALSE, T_DEFAULT, T_ARRAY]); + + $this->assertSame(T_STRING, $tokens[$enumCaseName]['code']); + $this->assertSame('T_STRING', $tokens[$enumCaseName]['type']); + + }//end testKeywordAsEnumCaseNameShouldBeString() + + + /** + * Data provider. + * + * @see testKeywordAsEnumCaseNameShouldBeString() + * + * @return array + */ + public function dataKeywordAsEnumCaseNameShouldBeString() + { + return [ + ['/* testKeywordAsEnumCaseNameShouldBeString1 */'], + ['/* testKeywordAsEnumCaseNameShouldBeString2 */'], + ['/* testKeywordAsEnumCaseNameShouldBeString3 */'], + ['/* testKeywordAsEnumCaseNameShouldBeString4 */'], + ]; + + }//end dataKeywordAsEnumCaseNameShouldBeString() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc new file mode 100644 index 000000000..e65600b6b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.inc @@ -0,0 +1,40 @@ +finally = 'foo'; + } +} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php new file mode 100644 index 000000000..2b28bc5d3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/FinallyTest.php @@ -0,0 +1,96 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class FinallyTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the finally keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataFinallyKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testFinallyKeyword($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_FINALLY, T_STRING]); + $this->assertSame(T_FINALLY, $tokens[$target]['code']); + $this->assertSame('T_FINALLY', $tokens[$target]['type']); + + }//end testFinallyKeyword() + + + /** + * Data provider. + * + * @see testFinallyKeyword() + * + * @return array + */ + public function dataFinallyKeyword() + { + return [ + ['/* testTryCatchFinally */'], + ['/* testTryFinallyCatch */'], + ['/* testTryFinally */'], + ]; + + }//end dataFinallyKeyword() + + + /** + * Test that 'finally' when not used as the reserved keyword is tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataFinallyNonKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testFinallyNonKeyword($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, [T_FINALLY, T_STRING]); + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testFinallyNonKeyword() + + + /** + * Data provider. + * + * @see testFinallyNonKeyword() + * + * @return array + */ + public function dataFinallyNonKeyword() + { + return [ + ['/* testFinallyUsedAsClassConstantName */'], + ['/* testFinallyUsedAsMethodName */'], + ['/* testFinallyUsedAsPropertyName */'], + ]; + + }//end dataFinallyNonKeyword() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc new file mode 100644 index 000000000..12df5d296 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.inc @@ -0,0 +1,56 @@ + +
    + +property: + // Do something. + break; +} + +switch (true) { + /* testNotGotoDeclarationGlobalConstantInTernary */ + case $x === ($cond) ? CONST_A : CONST_B: + // Do something. + break; +} + +/* testNotGotoDeclarationEnumWithType */ +enum Suit: string implements Colorful, CardGame {} diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php new file mode 100644 index 000000000..0f937cc8b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/GotoLabelTest.php @@ -0,0 +1,175 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class GotoLabelTest extends AbstractMethodUnitTest +{ + + + /** + * Verify that the label in a goto statement is tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataGotoStatement + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testGotoStatement($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, T_STRING); + + $this->assertInternalType('int', $label); + $this->assertSame($testContent, $tokens[$label]['content']); + + }//end testGotoStatement() + + + /** + * Data provider. + * + * @see testGotoStatement() + * + * @return array + */ + public function dataGotoStatement() + { + return [ + [ + '/* testGotoStatement */', + 'marker', + ], + [ + '/* testGotoStatementInLoop */', + 'end', + ], + ]; + + }//end dataGotoStatement() + + + /** + * Verify that the label in a goto declaration is tokenized as T_GOTO_LABEL. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataGotoDeclaration + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testGotoDeclaration($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, T_GOTO_LABEL); + + $this->assertInternalType('int', $label); + $this->assertSame($testContent, $tokens[$label]['content']); + + }//end testGotoDeclaration() + + + /** + * Data provider. + * + * @see testGotoDeclaration() + * + * @return array + */ + public function dataGotoDeclaration() + { + return [ + [ + '/* testGotoDeclaration */', + 'marker:', + ], + [ + '/* testGotoDeclarationOutsideLoop */', + 'end:', + ], + ]; + + }//end dataGotoDeclaration() + + + /** + * Verify that the constant used in a switch - case statement is not confused with a goto label. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataNotAGotoDeclaration + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotAGotoDeclaration($testMarker, $testContent) + { + $tokens = self::$phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_GOTO_LABEL, T_STRING], $testContent); + + $this->assertSame(T_STRING, $tokens[$target]['code']); + $this->assertSame('T_STRING', $tokens[$target]['type']); + + }//end testNotAGotoDeclaration() + + + /** + * Data provider. + * + * @see testNotAGotoDeclaration() + * + * @return array + */ + public function dataNotAGotoDeclaration() + { + return [ + [ + '/* testNotGotoDeclarationGlobalConstant */', + 'CONSTANT', + ], + [ + '/* testNotGotoDeclarationNamespacedConstant */', + 'CONSTANT', + ], + [ + '/* testNotGotoDeclarationClassConstant */', + 'CONSTANT', + ], + [ + '/* testNotGotoDeclarationClassProperty */', + 'property', + ], + [ + '/* testNotGotoDeclarationGlobalConstantInTernary */', + 'CONST_A', + ], + [ + '/* testNotGotoDeclarationGlobalConstantInTernary */', + 'CONST_B', + ], + [ + '/* testNotGotoDeclarationEnumWithType */', + 'Suit', + ], + ]; + + }//end dataNotAGotoDeclaration() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc new file mode 100644 index 000000000..4497f5c38 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.inc @@ -0,0 +1,404 @@ +getPos(skip: false), + count: count(array_or_countable: $array), + value: 50 +); + +array_fill( + start_index: /* testNestedFunctionCallInner1 */ $obj->getPos(skip: false), + count: /* testNestedFunctionCallInner2 */ count(array_or_countable: $array), + value: 50 +); + +/* testNamespaceOperatorFunction */ +namespace\function_name(label:$string, more: false); + +/* testNamespaceRelativeFunction */ +Partially\Qualified\function_name(label:$string, more: false); + +/* testNamespacedFQNFunction */ +\Fully\Qualified\function_name(label: $string, more:false); + +/* testVariableFunction */ +$fn(label: $string, more:false); + +/* testVariableVariableFunction */ +${$fn}(label: $string, more:false); + +/* testMethodCall */ +$obj->methodName(label: $foo, more: $bar); + +/* testVariableMethodCall */ +$obj->{$var}(label: $foo, more: $bar); + +/* testClassInstantiation */ +$obj = new MyClass(label: $string, more:false); + +/* testClassInstantiationSelf */ +$obj = new self(label: $string, more:true); + +/* testClassInstantiationStatic */ +$obj = new static(label: $string, more:false); + +/* testAnonClass */ +$anon = new class(label: $string, more: false) { + public function __construct($label, $more) {} +}; + +function myfoo( $💩💩💩, $Пасха, $_valid) {} +/* testNonAsciiNames */ +foo(💩💩💩: [], Пасха: 'text', _valid: 123); + +/* testMixedPositionalAndNamedArgsWithTernary */ +foo( $cond ? true : false, name: $value2 ); + +/* testNamedArgWithTernary */ +foo( label: $cond ? true : false, more: $cond ? CONSTANT_A : CONSTANT_B ); + +/* testTernaryWithFunctionCallsInThenElse */ +echo $cond ? foo( label: $something ) : foo( more: $something_else ); + +/* testTernaryWithConstantsInThenElse */ +echo $cond ? CONSTANT_NAME : OTHER_CONSTANT; + +switch ($s) { + /* testSwitchCaseWithConstant */ + case MY_CONSTANT: + // Do something. + break; + + /* testSwitchCaseWithClassProperty */ + case $obj->property: + // Do something. + break; + + /* testSwitchDefault */ + default: + // Do something. + break; +} + +/* testTernaryWithClosuresAndReturnTypes */ +$closure = $cond ? function() : bool {return true;} : function() : int {return 123;}; + +/* testTernaryWithArrowFunctionsAndReturnTypes */ +$fn = $cond ? fn() : bool => true : fn() : int => 123; + + +/* testCompileErrorNamedBeforePositional */ +// Not the concern of PHPCS. Should still be handled. +test(param: $bar, $foo); + +/* testDuplicateName1 */ +// Error Exception, but not the concern of PHPCS. Should still be handled. +test(param: 1, /* testDuplicateName2 */ param: 2); + +/* testIncorrectOrderWithVariadic */ +// Error Exception, but not the concern of PHPCS. Should still be handled. +array_fill(start_index: 0, ...[100, 50]); + +/* testCompileErrorIncorrectOrderWithVariadic */ +// Not the concern of PHPCS. Should still be handled. +test(...$values, param: $value); // Compile-time error + +/* testParseErrorNoValue */ +// Not the concern of PHPCS. Should still be handled. +test(param1:, param2:); + +/* testParseErrorDynamicName */ +// Parse error. Ignore. +function_name($variableStoringParamName: $value); + +/* testParseErrorExit */ +// Exit is a language construct, not a function. Named params not supported, handle it anyway. +exit(status: $value); + +/* testParseErrorEmpty */ +// Empty is a language construct, not a function. Named params not supported, handle it anyway. +empty(variable: $value); + +/* testParseErrorEval */ +// Eval is a language construct, not a function. Named params not supported, handle it anyway. +eval(code: $value); + +/* testParseErrorArbitraryParentheses */ +// Parse error. Not named param, handle it anyway. +$calc = (something: $value / $other); + + +/* testReservedKeywordAbstract1 */ +foobar(abstract: $value, /* testReservedKeywordAbstract2 */ abstract: $value); + +/* testReservedKeywordAnd1 */ +foobar(and: $value, /* testReservedKeywordAnd2 */ and: $value); + +/* testReservedKeywordArray1 */ +foobar(array: $value, /* testReservedKeywordArray2 */ array: $value); + +/* testReservedKeywordAs1 */ +foobar(as: $value, /* testReservedKeywordAs2 */ as: $value); + +/* testReservedKeywordBreak1 */ +foobar(break: $value, /* testReservedKeywordBreak2 */ break: $value); + +/* testReservedKeywordCallable1 */ +foobar(callable: $value, /* testReservedKeywordCallable2 */ callable: $value); + +/* testReservedKeywordCase1 */ +foobar(case: $value, /* testReservedKeywordCase2 */ case: $value); + +/* testReservedKeywordCatch1 */ +foobar(catch: $value, /* testReservedKeywordCatch2 */ catch: $value); + +/* testReservedKeywordClass1 */ +foobar(class: $value, /* testReservedKeywordClass2 */ class: $value); + +/* testReservedKeywordClone1 */ +foobar(clone: $value, /* testReservedKeywordClone2 */ clone: $value); + +/* testReservedKeywordConst1 */ +foobar(const: $value, /* testReservedKeywordConst2 */ const: $value); + +/* testReservedKeywordContinue1 */ +foobar(continue: $value, /* testReservedKeywordContinue2 */ continue: $value); + +/* testReservedKeywordDeclare1 */ +foobar(declare: $value, /* testReservedKeywordDeclare2 */ declare: $value); + +/* testReservedKeywordDefault1 */ +foobar(default: $value, /* testReservedKeywordDefault2 */ default: $value); + +/* testReservedKeywordDie1 */ +foobar(die: $value, /* testReservedKeywordDie2 */ die: $value); + +/* testReservedKeywordDo1 */ +foobar(do: $value, /* testReservedKeywordDo2 */ do: $value); + +/* testReservedKeywordEcho1 */ +foobar(echo: $value, /* testReservedKeywordEcho2 */ echo: $value); + +/* testReservedKeywordElse1 */ +foobar(else: $value, /* testReservedKeywordElse2 */ else: $value); + +/* testReservedKeywordElseif1 */ +foobar(elseif: $value, /* testReservedKeywordElseif2 */ elseif: $value); + +/* testReservedKeywordEmpty1 */ +foobar(empty: $value, /* testReservedKeywordEmpty2 */ empty: $value); + +/* testReservedKeywordEnddeclare1 */ +foobar(enddeclare: $value, /* testReservedKeywordEnddeclare2 */ enddeclare: $value); + +/* testReservedKeywordEndfor1 */ +foobar(endfor: $value, /* testReservedKeywordEndfor2 */ endfor: $value); + +/* testReservedKeywordEndforeach1 */ +foobar(endforeach: $value, /* testReservedKeywordEndforeach2 */ endforeach: $value); + +/* testReservedKeywordEndif1 */ +foobar(endif: $value, /* testReservedKeywordEndif2 */ endif: $value); + +/* testReservedKeywordEndswitch1 */ +foobar(endswitch: $value, /* testReservedKeywordEndswitch2 */ endswitch: $value); + +/* testReservedKeywordEndwhile1 */ +foobar(endwhile: $value, /* testReservedKeywordEndwhile2 */ endwhile: $value); + +/* testReservedKeywordEval1 */ +foobar(eval: $value, /* testReservedKeywordEval2 */ eval: $value); + +/* testReservedKeywordExit1 */ +foobar(exit: $value, /* testReservedKeywordExit2 */ exit: $value); + +/* testReservedKeywordExtends1 */ +foobar(extends: $value, /* testReservedKeywordExtends2 */ extends: $value); + +/* testReservedKeywordFinal1 */ +foobar(final: $value, /* testReservedKeywordFinal2 */ final: $value); + +/* testReservedKeywordFinally1 */ +foobar(finally: $value, /* testReservedKeywordFinally2 */ finally: $value); + +/* testReservedKeywordFn1 */ +foobar(fn: $value, /* testReservedKeywordFn2 */ fn: $value); + +/* testReservedKeywordFor1 */ +foobar(for: $value, /* testReservedKeywordFor2 */ for: $value); + +/* testReservedKeywordForeach1 */ +foobar(foreach: $value, /* testReservedKeywordForeach2 */ foreach: $value); + +/* testReservedKeywordFunction1 */ +foobar(function: $value, /* testReservedKeywordFunction2 */ function: $value); + +/* testReservedKeywordGlobal1 */ +foobar(global: $value, /* testReservedKeywordGlobal2 */ global: $value); + +/* testReservedKeywordGoto1 */ +foobar(goto: $value, /* testReservedKeywordGoto2 */ goto: $value); + +/* testReservedKeywordIf1 */ +foobar(if: $value, /* testReservedKeywordIf2 */ if: $value); + +/* testReservedKeywordImplements1 */ +foobar(implements: $value, /* testReservedKeywordImplements2 */ implements: $value); + +/* testReservedKeywordInclude1 */ +foobar(include: $value, /* testReservedKeywordInclude2 */ include: $value); + +/* testReservedKeywordInclude_once1 */ +foobar(include_once: $value, /* testReservedKeywordInclude_once2 */ include_once: $value); + +/* testReservedKeywordInstanceof1 */ +foobar(instanceof: $value, /* testReservedKeywordInstanceof2 */ instanceof: $value); + +/* testReservedKeywordInsteadof1 */ +foobar(insteadof: $value, /* testReservedKeywordInsteadof2 */ insteadof: $value); + +/* testReservedKeywordInterface1 */ +foobar(interface: $value, /* testReservedKeywordInterface2 */ interface: $value); + +/* testReservedKeywordIsset1 */ +foobar(isset: $value, /* testReservedKeywordIsset2 */ isset: $value); + +/* testReservedKeywordList1 */ +foobar(list: $value, /* testReservedKeywordList2 */ list: $value); + +/* testReservedKeywordMatch1 */ +foobar(match: $value, /* testReservedKeywordMatch2 */ match: $value); + +/* testReservedKeywordNamespace1 */ +foobar(namespace: $value, /* testReservedKeywordNamespace2 */ namespace: $value); + +/* testReservedKeywordNew1 */ +foobar(new: $value, /* testReservedKeywordNew2 */ new: $value); + +/* testReservedKeywordOr1 */ +foobar(or: $value, /* testReservedKeywordOr2 */ or: $value); + +/* testReservedKeywordPrint1 */ +foobar(print: $value, /* testReservedKeywordPrint2 */ print: $value); + +/* testReservedKeywordPrivate1 */ +foobar(private: $value, /* testReservedKeywordPrivate2 */ private: $value); + +/* testReservedKeywordProtected1 */ +foobar(protected: $value, /* testReservedKeywordProtected2 */ protected: $value); + +/* testReservedKeywordPublic1 */ +foobar(public: $value, /* testReservedKeywordPublic2 */ public: $value); + +/* testReservedKeywordReadonly1 */ +foobar(readonly: $value, /* testReservedKeywordReadonly2 */ readonly: $value); + +/* testReservedKeywordRequire1 */ +foobar(require: $value, /* testReservedKeywordRequire2 */ require: $value); + +/* testReservedKeywordRequire_once1 */ +foobar(require_once: $value, /* testReservedKeywordRequire_once2 */ require_once: $value); + +/* testReservedKeywordReturn1 */ +foobar(return: $value, /* testReservedKeywordReturn2 */ return: $value); + +/* testReservedKeywordStatic1 */ +foobar(static: $value, /* testReservedKeywordStatic2 */ static: $value); + +/* testReservedKeywordSwitch1 */ +foobar(switch: $value, /* testReservedKeywordSwitch2 */ switch: $value); + +/* testReservedKeywordThrow1 */ +foobar(throw: $value, /* testReservedKeywordThrow2 */ throw: $value); + +/* testReservedKeywordTrait1 */ +foobar(trait: $value, /* testReservedKeywordTrait2 */ trait: $value); + +/* testReservedKeywordTry1 */ +foobar(try: $value, /* testReservedKeywordTry2 */ try: $value); + +/* testReservedKeywordUnset1 */ +foobar(unset: $value, /* testReservedKeywordUnset2 */ unset: $value); + +/* testReservedKeywordUse1 */ +foobar(use: $value, /* testReservedKeywordUse2 */ use: $value); + +/* testReservedKeywordVar1 */ +foobar(var: $value, /* testReservedKeywordVar2 */ var: $value); + +/* testReservedKeywordWhile1 */ +foobar(while: $value, /* testReservedKeywordWhile2 */ while: $value); + +/* testReservedKeywordXor1 */ +foobar(xor: $value, /* testReservedKeywordXor2 */ xor: $value); + +/* testReservedKeywordYield1 */ +foobar(yield: $value, /* testReservedKeywordYield2 */ yield: $value); + +/* testReservedKeywordInt1 */ +foobar(int: $value, /* testReservedKeywordInt2 */ int: $value); + +/* testReservedKeywordFloat1 */ +foobar(float: $value, /* testReservedKeywordFloat2 */ float: $value); + +/* testReservedKeywordBool1 */ +foobar(bool: $value, /* testReservedKeywordBool2 */ bool: $value); + +/* testReservedKeywordString1 */ +foobar(string: $value, /* testReservedKeywordString2 */ string: $value); + +/* testReservedKeywordTrue1 */ +foobar(true: $value, /* testReservedKeywordTrue2 */ true: $value); + +/* testReservedKeywordFalse1 */ +foobar(false: $value, /* testReservedKeywordFalse2 */ false: $value); + +/* testReservedKeywordNull1 */ +foobar(null: $value, /* testReservedKeywordNull2 */ null: $value); + +/* testReservedKeywordVoid1 */ +foobar(void: $value, /* testReservedKeywordVoid2 */ void: $value); + +/* testReservedKeywordIterable1 */ +foobar(iterable: $value, /* testReservedKeywordIterable2 */ iterable: $value); + +/* testReservedKeywordObject1 */ +foobar(object: $value, /* testReservedKeywordObject2 */ object: $value); + +/* testReservedKeywordResource1 */ +foobar(resource: $value, /* testReservedKeywordResource2 */ resource: $value); + +/* testReservedKeywordMixed1 */ +foobar(mixed: $value, /* testReservedKeywordMixed2 */ mixed: $value); + +/* testReservedKeywordNumeric1 */ +foobar(numeric: $value, /* testReservedKeywordNumeric2 */ numeric: $value); + +/* testReservedKeywordParent1 */ +foobar(parent: $value, /* testReservedKeywordParent2 */ parent: $value); + +/* testReservedKeywordSelf1 */ +foobar(self: $value, /* testReservedKeywordSelf2 */ self: $value); + +/* testReservedKeywordNever1 */ +foobar(never: $value, /* testReservedKeywordNever2 */ never: $value); diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php new file mode 100644 index 000000000..0a878c1d3 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NamedFunctionCallArgumentsTest.php @@ -0,0 +1,884 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class NamedFunctionCallArgumentsTest extends AbstractMethodUnitTest +{ + + + /** + * Verify that parameter labels are tokenized as T_PARAM_NAME and that + * the colon after it is tokenized as a T_COLON. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $parameters The token content for each parameter label to look for. + * + * @dataProvider dataNamedFunctionCallArguments + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNamedFunctionCallArguments($testMarker, $parameters) + { + $tokens = self::$phpcsFile->getTokens(); + + foreach ($parameters as $content) { + $label = $this->getTargetToken($testMarker, [T_STRING, T_PARAM_NAME], $content); + + $this->assertSame( + T_PARAM_NAME, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (code)' + ); + $this->assertSame( + 'T_PARAM_NAME', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (type)' + ); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + }//end foreach + + }//end testNamedFunctionCallArguments() + + + /** + * Data provider. + * + * @see testNamedFunctionCallArguments() + * + * @return array + */ + public function dataNamedFunctionCallArguments() + { + return [ + [ + '/* testNamedArgs */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testNamedArgsMultiline */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testNamedArgsWithWhitespaceAndComments */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testMixedPositionalAndNamedArgs */', + ['double_encode'], + ], + [ + '/* testNestedFunctionCallOuter */', + [ + 'start_index', + 'count', + 'value', + ], + ], + [ + '/* testNestedFunctionCallInner1 */', + ['skip'], + ], + [ + '/* testNestedFunctionCallInner2 */', + ['array_or_countable'], + ], + [ + '/* testNamespaceOperatorFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testNamespaceRelativeFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testNamespacedFQNFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testVariableFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testVariableVariableFunction */', + [ + 'label', + 'more', + ], + ], + [ + '/* testMethodCall */', + [ + 'label', + 'more', + ], + ], + [ + '/* testVariableMethodCall */', + [ + 'label', + 'more', + ], + ], + [ + '/* testClassInstantiation */', + [ + 'label', + 'more', + ], + ], + [ + '/* testClassInstantiationSelf */', + [ + 'label', + 'more', + ], + ], + [ + '/* testClassInstantiationStatic */', + [ + 'label', + 'more', + ], + ], + [ + '/* testAnonClass */', + [ + 'label', + 'more', + ], + ], + [ + '/* testNonAsciiNames */', + [ + '💩💩💩', + 'Пасха', + '_valid', + ], + ], + + // Coding errors which should still be handled. + [ + '/* testCompileErrorNamedBeforePositional */', + ['param'], + ], + [ + '/* testDuplicateName1 */', + ['param'], + ], + [ + '/* testDuplicateName2 */', + ['param'], + ], + [ + '/* testIncorrectOrderWithVariadic */', + ['start_index'], + ], + [ + '/* testCompileErrorIncorrectOrderWithVariadic */', + ['param'], + ], + [ + '/* testParseErrorNoValue */', + [ + 'param1', + 'param2', + ], + ], + [ + '/* testParseErrorExit */', + ['status'], + ], + [ + '/* testParseErrorEmpty */', + ['variable'], + ], + [ + '/* testParseErrorEval */', + ['code'], + ], + [ + '/* testParseErrorArbitraryParentheses */', + ['something'], + ], + ]; + + }//end dataNamedFunctionCallArguments() + + + /** + * Verify that other T_STRING tokens within a function call are still tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $content The token content to look for. + * + * @dataProvider dataOtherTstringInFunctionCall + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testOtherTstringInFunctionCall($testMarker, $content) + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, [T_STRING, T_PARAM_NAME], $content); + + $this->assertSame( + T_STRING, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_STRING (code)' + ); + $this->assertSame( + 'T_STRING', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_STRING (type)' + ); + + }//end testOtherTstringInFunctionCall() + + + /** + * Data provider. + * + * @see testOtherTstringInFunctionCall() + * + * @return array + */ + public function dataOtherTstringInFunctionCall() + { + return [ + [ + '/* testPositionalArgs */', + 'START_INDEX', + ], + [ + '/* testPositionalArgs */', + 'COUNT', + ], + [ + '/* testPositionalArgs */', + 'VALUE', + ], + [ + '/* testNestedFunctionCallInner2 */', + 'count', + ], + ]; + + }//end dataOtherTstringInFunctionCall() + + + /** + * Verify whether the colons are tokenized correctly when a ternary is used in a mixed + * positional and named arguments function call. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMixedPositionalAndNamedArgsWithTernary() + { + $tokens = self::$phpcsFile->getTokens(); + + $true = $this->getTargetToken('/* testMixedPositionalAndNamedArgsWithTernary */', T_TRUE); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + $label = $this->getTargetToken('/* testMixedPositionalAndNamedArgsWithTernary */', T_PARAM_NAME, 'name'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testMixedPositionalAndNamedArgsWithTernary() + + + /** + * Verify whether the colons are tokenized correctly when a ternary is used + * in a named arguments function call. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNamedArgWithTernary() + { + $tokens = self::$phpcsFile->getTokens(); + + /* + * First argument. + */ + + $label = $this->getTargetToken('/* testNamedArgWithTernary */', T_PARAM_NAME, 'label'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'First arg: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'First arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'First arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $true = $this->getTargetToken('/* testNamedArgWithTernary */', T_TRUE); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'First arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'First arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + /* + * Second argument. + */ + + $label = $this->getTargetToken('/* testNamedArgWithTernary */', T_PARAM_NAME, 'more'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Second arg: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Second arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Second arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $true = $this->getTargetToken('/* testNamedArgWithTernary */', T_STRING, 'CONSTANT_A'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Second arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Second arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + }//end testNamedArgWithTernary() + + + /** + * Verify whether the colons are tokenized correctly when named arguments + * function calls are used in a ternary. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryWithFunctionCallsInThenElse() + { + $tokens = self::$phpcsFile->getTokens(); + + /* + * Then. + */ + + $label = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_PARAM_NAME, 'label'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Function in then: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Function in then: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Function in then: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $closeParens = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_CLOSE_PARENTHESIS); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($closeParens + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + /* + * Else. + */ + + $label = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_PARAM_NAME, 'more'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Function in else: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Function in else: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Function in else: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testTernaryWithFunctionCallsInThenElse() + + + /** + * Verify whether the colons are tokenized correctly when constants are used in a ternary. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryWithConstantsInThenElse() + { + $tokens = self::$phpcsFile->getTokens(); + + $constant = $this->getTargetToken('/* testTernaryWithConstantsInThenElse */', T_STRING, 'CONSTANT_NAME'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($constant + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + }//end testTernaryWithConstantsInThenElse() + + + /** + * Verify whether the colons are tokenized correctly in a switch statement. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testSwitchStatement() + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken('/* testSwitchCaseWithConstant */', T_STRING, 'MY_CONSTANT'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'First case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'First case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $label = $this->getTargetToken('/* testSwitchCaseWithClassProperty */', T_STRING, 'property'); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Second case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Second case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $default = $this->getTargetToken('/* testSwitchDefault */', T_DEFAULT); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($default + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Default case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Default case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testSwitchStatement() + + + /** + * Verify that a variable parameter label (parse error) is still tokenized as T_VARIABLE. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testParseErrorVariableLabel() + { + $tokens = self::$phpcsFile->getTokens(); + + $label = $this->getTargetToken('/* testParseErrorDynamicName */', [T_VARIABLE, T_PARAM_NAME], '$variableStoringParamName'); + + $this->assertSame( + T_VARIABLE, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_VARIABLE (code)' + ); + $this->assertSame( + 'T_VARIABLE', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_VARIABLE (type)' + ); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testParseErrorVariableLabel() + + + /** + * Verify that reserved keywords used as a parameter label are tokenized as T_PARAM_NAME + * and that the colon after it is tokenized as a T_COLON. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $tokenTypes The token codes to look for. + * @param string $tokenContent The token content to look for. + * + * @dataProvider dataReservedKeywordsAsName + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testReservedKeywordsAsName($testMarker, $tokenTypes, $tokenContent) + { + $tokens = self::$phpcsFile->getTokens(); + $label = $this->getTargetToken($testMarker, $tokenTypes, $tokenContent); + + $this->assertSame( + T_PARAM_NAME, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (code)' + ); + $this->assertSame( + 'T_PARAM_NAME', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (type)' + ); + + // Get the next non-empty token. + $colon = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testReservedKeywordsAsName() + + + /** + * Data provider. + * + * @see testReservedKeywordsAsName() + * + * @return array + */ + public function dataReservedKeywordsAsName() + { + $reservedKeywords = [ + // '__halt_compiler', NOT TESTABLE + 'abstract', + 'and', + 'array', + 'as', + 'break', + 'callable', + 'case', + 'catch', + 'class', + 'clone', + 'const', + 'continue', + 'declare', + 'default', + 'die', + 'do', + 'echo', + 'else', + 'elseif', + 'empty', + 'enddeclare', + 'endfor', + 'endforeach', + 'endif', + 'endswitch', + 'endwhile', + 'eval', + 'exit', + 'extends', + 'final', + 'finally', + 'fn', + 'for', + 'foreach', + 'function', + 'global', + 'goto', + 'if', + 'implements', + 'include', + 'include_once', + 'instanceof', + 'insteadof', + 'interface', + 'isset', + 'list', + 'match', + 'namespace', + 'new', + 'or', + 'print', + 'private', + 'protected', + 'public', + 'readonly', + 'require', + 'require_once', + 'return', + 'static', + 'switch', + 'throw', + 'trait', + 'try', + 'unset', + 'use', + 'var', + 'while', + 'xor', + 'yield', + 'int', + 'float', + 'bool', + 'string', + 'true', + 'false', + 'null', + 'void', + 'iterable', + 'object', + 'resource', + 'mixed', + 'numeric', + 'never', + + // Not reserved keyword, but do have their own token in PHPCS. + 'parent', + 'self', + ]; + + $data = []; + + foreach ($reservedKeywords as $keyword) { + $tokensTypes = [ + T_PARAM_NAME, + T_STRING, + T_GOTO_LABEL, + ]; + $tokenName = 'T_'.strtoupper($keyword); + + if ($keyword === 'and') { + $tokensTypes[] = T_LOGICAL_AND; + } else if ($keyword === 'die') { + $tokensTypes[] = T_EXIT; + } else if ($keyword === 'or') { + $tokensTypes[] = T_LOGICAL_OR; + } else if ($keyword === 'xor') { + $tokensTypes[] = T_LOGICAL_XOR; + } else if ($keyword === '__halt_compiler') { + $tokensTypes[] = T_HALT_COMPILER; + } else if (defined($tokenName) === true) { + $tokensTypes[] = constant($tokenName); + } + + $data[$keyword.'FirstParam'] = [ + '/* testReservedKeyword'.ucfirst($keyword).'1 */', + $tokensTypes, + $keyword, + ]; + + $data[$keyword.'SecondParam'] = [ + '/* testReservedKeyword'.ucfirst($keyword).'2 */', + $tokensTypes, + $keyword, + ]; + }//end foreach + + return $data; + + }//end dataReservedKeywordsAsName() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc new file mode 100644 index 000000000..982841eac --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc @@ -0,0 +1,29 @@ +foo; + +/* testNullsafeObjectOperator */ +echo $obj?->foo; + +/* testNullsafeObjectOperatorWriteContext */ +// Intentional parse error, but not the concern of the tokenizer. +$foo?->bar->baz = 'baz'; + +/* testTernaryThen */ +echo $obj ? $obj->prop : $other->prop; + +/* testParseErrorWhitespaceNotAllowed */ +echo $obj ? + -> foo; + +/* testParseErrorCommentNotAllowed */ +echo $obj ?/*comment*/-> foo; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +echo $obj? diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php new file mode 100644 index 000000000..8e465a3be --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/NullsafeObjectOperatorTest.php @@ -0,0 +1,140 @@ += 8.0 nullsafe object operator. + * + * @author Juliette Reinders Folmer + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class NullsafeObjectOperatorTest extends AbstractMethodUnitTest +{ + + /** + * Tokens to search for. + * + * @var array + */ + protected $find = [ + T_NULLSAFE_OBJECT_OPERATOR, + T_OBJECT_OPERATOR, + T_INLINE_THEN, + ]; + + + /** + * Test that a normal object operator is still tokenized as such. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testObjectOperator() + { + $tokens = self::$phpcsFile->getTokens(); + + $operator = $this->getTargetToken('/* testObjectOperator */', $this->find); + $this->assertSame(T_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is object operator'); + $this->assertSame('T_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is object operator'); + + }//end testObjectOperator() + + + /** + * Test that a nullsafe object operator is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNullsafeObjectOperator + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNullsafeObjectOperator($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $operator = $this->getTargetToken($testMarker, $this->find); + $this->assertSame(T_NULLSAFE_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is nullsafe object operator'); + $this->assertSame('T_NULLSAFE_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is nullsafe object operator'); + + }//end testNullsafeObjectOperator() + + + /** + * Data provider. + * + * @see testNullsafeObjectOperator() + * + * @return array + */ + public function dataNullsafeObjectOperator() + { + return [ + ['/* testNullsafeObjectOperator */'], + ['/* testNullsafeObjectOperatorWriteContext */'], + ]; + + }//end dataNullsafeObjectOperator() + + + /** + * Test that a question mark not followed by an object operator is tokenized as T_TERNARY_THEN. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param bool $testObjectOperator Whether to test for the next non-empty token being tokenized + * as an object operator. + * + * @dataProvider dataTernaryThen + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryThen($testMarker, $testObjectOperator=false) + { + $tokens = self::$phpcsFile->getTokens(); + + $operator = $this->getTargetToken($testMarker, $this->find); + $this->assertSame(T_INLINE_THEN, $tokens[$operator]['code'], 'Failed asserting code is inline then'); + $this->assertSame('T_INLINE_THEN', $tokens[$operator]['type'], 'Failed asserting type is inline then'); + + if ($testObjectOperator === true) { + $next = self::$phpcsFile->findNext(Tokens::$emptyTokens, ($operator + 1), null, true); + $this->assertSame(T_OBJECT_OPERATOR, $tokens[$next]['code'], 'Failed asserting code is object operator'); + $this->assertSame('T_OBJECT_OPERATOR', $tokens[$next]['type'], 'Failed asserting type is object operator'); + } + + }//end testTernaryThen() + + + /** + * Data provider. + * + * @see testTernaryThen() + * + * @return array + */ + public function dataTernaryThen() + { + return [ + ['/* testTernaryThen */'], + [ + '/* testParseErrorWhitespaceNotAllowed */', + true, + ], + [ + '/* testParseErrorCommentNotAllowed */', + true, + ], + ['/* testLiveCoding */'], + ]; + + }//end dataTernaryThen() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc new file mode 100644 index 000000000..e2d61bb66 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc @@ -0,0 +1,19 @@ + new namespace\Baz; diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php new file mode 100644 index 000000000..23cbd9877 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php @@ -0,0 +1,98 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class ScopeSettingWithNamespaceOperatorTest extends AbstractMethodUnitTest +{ + + + /** + * Test that the scope opener/closers are set correctly when the namespace keyword is encountered as an operator. + * + * @param string $testMarker The comment which prefaces the target tokens in the test file. + * @param int|string[] $tokenTypes The token type to search for. + * @param int|string[] $open Optional. The token type for the scope opener. + * @param int|string[] $close Optional. The token type for the scope closer. + * + * @dataProvider dataScopeSetting + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testScopeSetting($testMarker, $tokenTypes, $open=T_OPEN_CURLY_BRACKET, $close=T_CLOSE_CURLY_BRACKET) + { + $tokens = self::$phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, $tokenTypes); + $opener = $this->getTargetToken($testMarker, $open); + $closer = $this->getTargetToken($testMarker, $close); + + $this->assertArrayHasKey('scope_opener', $tokens[$target], 'Scope opener missing'); + $this->assertArrayHasKey('scope_closer', $tokens[$target], 'Scope closer missing'); + $this->assertSame($opener, $tokens[$target]['scope_opener'], 'Scope opener not same'); + $this->assertSame($closer, $tokens[$target]['scope_closer'], 'Scope closer not same'); + + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Scope opener missing for open curly'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Scope closer missing for open curly'); + $this->assertSame($opener, $tokens[$opener]['scope_opener'], 'Scope opener not same for open curly'); + $this->assertSame($closer, $tokens[$opener]['scope_closer'], 'Scope closer not same for open curly'); + + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Scope opener missing for close curly'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Scope closer missing for close curly'); + $this->assertSame($opener, $tokens[$closer]['scope_opener'], 'Scope opener not same for close curly'); + $this->assertSame($closer, $tokens[$closer]['scope_closer'], 'Scope closer not same for close curly'); + + }//end testScopeSetting() + + + /** + * Data provider. + * + * @see testScopeSetting() + * + * @return array + */ + public function dataScopeSetting() + { + return [ + [ + '/* testClassExtends */', + [T_CLASS], + ], + [ + '/* testClassImplements */', + [T_ANON_CLASS], + ], + [ + '/* testInterfaceExtends */', + [T_INTERFACE], + ], + [ + '/* testFunctionReturnType */', + [T_FUNCTION], + ], + [ + '/* testClosureReturnType */', + [T_CLOSURE], + ], + [ + '/* testArrowFunctionReturnType */', + [T_FN], + [T_FN_ARROW], + [T_SEMICOLON], + ], + ]; + + }//end dataScopeSetting() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc new file mode 100644 index 000000000..54065f213 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.inc @@ -0,0 +1,97 @@ +function_call()[$x]; + +/* testStaticMethodCallDereferencing */ +$var = ClassName::function_call()[$x]; + +/* testPropertyDereferencing */ +$var = $obj->property[2]; + +/* testPropertyDereferencingWithInaccessibleName */ +$var = $ref->{'ref-type'}[1]; + +/* testStaticPropertyDereferencing */ +$var ClassName::$property[2]; + +/* testStringDereferencing */ +$var = 'PHP'[1]; + +/* testStringDereferencingDoubleQuoted */ +$var = "PHP"[$y]; + +/* testConstantDereferencing */ +$var = MY_CONSTANT[1]; + +/* testClassConstantDereferencing */ +$var ClassName::CONSTANT_NAME[2]; + +/* testMagicConstantDereferencing */ +$var = __FILE__[0]; + +/* testArrayAccessCurlyBraces */ +$var = $array{'key'}['key']; + +/* testArrayLiteralDereferencing */ +echo array(1, 2, 3)[0]; + +echo [1, 2, 3]/* testShortArrayLiteralDereferencing */[0]; + +/* testClassMemberDereferencingOnInstantiation1 */ +(new foo)[0]; + +/* testClassMemberDereferencingOnInstantiation2 */ +$a = (new Foo( array(1, array(4, 5), 3) ))[1][0]; + +/* testClassMemberDereferencingOnClone */ +echo (clone $iterable)[20]; + +/* testNullsafeMethodCallDereferencing */ +$var = $obj?->function_call()[$x]; + +/* testInterpolatedStringDereferencing */ +$var = "PHP{$rocks}"[1]; + +/* + * Short array brackets. + */ + +/* testShortArrayDeclarationEmpty */ +$array = []; + +/* testShortArrayDeclarationWithOneValue */ +$array = [1]; + +/* testShortArrayDeclarationWithMultipleValues */ +$array = [1, 2, 3]; + +/* testShortArrayDeclarationWithDereferencing */ +echo [1, 2, 3][0]; + +/* testShortListDeclaration */ +[ $a, $b ] = $array; + +[ $a, $b, /* testNestedListDeclaration */, [$c, $d]] = $array; + +/* testArrayWithinFunctionCall */ +$var = functionCall([$x, $y]); + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$array = [ diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php new file mode 100644 index 000000000..0484d4fcb --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/ShortArrayTest.php @@ -0,0 +1,132 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class ShortArrayTest extends AbstractMethodUnitTest +{ + + + /** + * Test that real square brackets are still tokenized as square brackets. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataSquareBrackets + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSquareBrackets($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]); + $this->assertSame(T_OPEN_SQUARE_BRACKET, $tokens[$opener]['code']); + $this->assertSame('T_OPEN_SQUARE_BRACKET', $tokens[$opener]['type']); + + if (isset($tokens[$opener]['bracket_closer']) === true) { + $closer = $tokens[$opener]['bracket_closer']; + $this->assertSame(T_CLOSE_SQUARE_BRACKET, $tokens[$closer]['code']); + $this->assertSame('T_CLOSE_SQUARE_BRACKET', $tokens[$closer]['type']); + } + + }//end testSquareBrackets() + + + /** + * Data provider. + * + * @see testSquareBrackets() + * + * @return array + */ + public function dataSquareBrackets() + { + return [ + ['/* testArrayAccess1 */'], + ['/* testArrayAccess2 */'], + ['/* testArrayAssignment */'], + ['/* testFunctionCallDereferencing */'], + ['/* testMethodCallDereferencing */'], + ['/* testStaticMethodCallDereferencing */'], + ['/* testPropertyDereferencing */'], + ['/* testPropertyDereferencingWithInaccessibleName */'], + ['/* testStaticPropertyDereferencing */'], + ['/* testStringDereferencing */'], + ['/* testStringDereferencingDoubleQuoted */'], + ['/* testConstantDereferencing */'], + ['/* testClassConstantDereferencing */'], + ['/* testMagicConstantDereferencing */'], + ['/* testArrayAccessCurlyBraces */'], + ['/* testArrayLiteralDereferencing */'], + ['/* testShortArrayLiteralDereferencing */'], + ['/* testClassMemberDereferencingOnInstantiation1 */'], + ['/* testClassMemberDereferencingOnInstantiation2 */'], + ['/* testClassMemberDereferencingOnClone */'], + ['/* testNullsafeMethodCallDereferencing */'], + ['/* testInterpolatedStringDereferencing */'], + ['/* testLiveCoding */'], + ]; + + }//end dataSquareBrackets() + + + /** + * Test that short arrays and short lists are still tokenized as short arrays. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataShortArrays + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testShortArrays($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]); + $this->assertSame(T_OPEN_SHORT_ARRAY, $tokens[$opener]['code']); + $this->assertSame('T_OPEN_SHORT_ARRAY', $tokens[$opener]['type']); + + if (isset($tokens[$opener]['bracket_closer']) === true) { + $closer = $tokens[$opener]['bracket_closer']; + $this->assertSame(T_CLOSE_SHORT_ARRAY, $tokens[$closer]['code']); + $this->assertSame('T_CLOSE_SHORT_ARRAY', $tokens[$closer]['type']); + } + + }//end testShortArrays() + + + /** + * Data provider. + * + * @see testShortArrays() + * + * @return array + */ + public function dataShortArrays() + { + return [ + ['/* testShortArrayDeclarationEmpty */'], + ['/* testShortArrayDeclarationWithOneValue */'], + ['/* testShortArrayDeclarationWithMultipleValues */'], + ['/* testShortArrayDeclarationWithDereferencing */'], + ['/* testShortListDeclaration */'], + ['/* testNestedListDeclaration */'], + ['/* testArrayWithinFunctionCall */'], + ]; + + }//end dataShortArrays() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc new file mode 100644 index 000000000..3bf013c66 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceTest.inc @@ -0,0 +1,139 @@ + + + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class StableCommentWhitespaceTest extends AbstractMethodUnitTest +{ + + + /** + * Test that comment tokenization with new lines at the end of the comment is stable. + * + * @param string $testMarker The comment prefacing the test. + * @param array $expectedTokens The tokenization expected. + * + * @dataProvider dataCommentTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testCommentTokenization($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $comment = $this->getTargetToken($testMarker, Tokens::$commentTokens); + + foreach ($expectedTokens as $key => $tokenInfo) { + $this->assertSame(constant($tokenInfo['type']), $tokens[$comment]['code']); + $this->assertSame($tokenInfo['type'], $tokens[$comment]['type']); + $this->assertSame($tokenInfo['content'], $tokens[$comment]['content']); + + ++$comment; + } + + }//end testCommentTokenization() + + + /** + * Data provider. + * + * @see testCommentTokenization() + * + * @return array + */ + public function dataCommentTokenization() + { + return [ + [ + '/* testSingleLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashAnnotation */', + [ + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// phpcs:disable Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationStart */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationMiddle */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineStarComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Single line star comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineStarCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineStarAnnotation */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '/* phpcs:ignore Stnd.Cat */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithAnnotationStart */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '/* @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithAnnotationMiddle */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => ' * phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineStarCommentWithAnnotationEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => ' * phpcs:ignore Stnd.Cat */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + + [ + '/* testSingleLineDocblockComment */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineDocblockCommentTrailing */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineDocblockAnnotation */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => 'phpcs:ignore Stnd.Cat.Sniff ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + + [ + '/* testMultiLineDocblockComment */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment1', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment2', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineDocblockCommentWithIndent */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment1', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment2', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineDocblockCommentWithAnnotation */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => 'phpcs:ignore Stnd.Cat', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineDocblockCommentWithTagAnnotation */', + [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '@phpcs:ignore Stnd.Cat', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Slash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testSingleLineHashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Hash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testCommentAtEndOfFile */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment', + ], + ], + ], + ]; + + }//end dataCommentTokenization() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc new file mode 100644 index 000000000..6ca7026d4 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/StableCommentWhitespaceWinTest.inc @@ -0,0 +1,63 @@ + + + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +class StableCommentWhitespaceWinTest extends AbstractMethodUnitTest +{ + + + /** + * Test that comment tokenization with new lines at the end of the comment is stable. + * + * @param string $testMarker The comment prefacing the test. + * @param array $expectedTokens The tokenization expected. + * + * @dataProvider dataCommentTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testCommentTokenization($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $comment = $this->getTargetToken($testMarker, Tokens::$commentTokens); + + foreach ($expectedTokens as $key => $tokenInfo) { + $this->assertSame(constant($tokenInfo['type']), $tokens[$comment]['code']); + $this->assertSame($tokenInfo['type'], $tokens[$comment]['type']); + $this->assertSame($tokenInfo['content'], $tokens[$comment]['content']); + + ++$comment; + } + + }//end testCommentTokenization() + + + /** + * Data provider. + * + * @see testCommentTokenization() + * + * @return array + */ + public function dataCommentTokenization() + { + return [ + [ + '/* testSingleLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashAnnotation */', + [ + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// phpcs:disable Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationStart */', + [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationMiddle */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineSlashCommentWithAnnotationEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineSlashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Slash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testSingleLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashCommentTrailing */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashComment */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testMultiLineHashCommentWithIndent */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testSingleLineHashCommentNoNewLineAtEnd */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Hash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + [ + '/* testCommentAtEndOfFile */', + [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment', + ], + ], + ], + ]; + + }//end dataCommentTokenization() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc new file mode 100644 index 000000000..abf9b85ba --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.inc @@ -0,0 +1,120 @@ + $param & $int; + +/* testTypeIntersectionArrowReturnType */ +$arrowWithReturnType = fn ($param) : Foo&Bar => $param * 10; + +/* testBitwiseAndInArrayKey */ +$array = array( + A & B => /* testBitwiseAndInArrayValue */ B & C +); + +/* testBitwiseAndInShortArrayKey */ +$array = [ + A & B => /* testBitwiseAndInShortArrayValue */ B & C +]; + +/* testBitwiseAndNonArrowFnFunctionCall */ +$obj->fn($something & $else); + +/* testBitwiseAnd6 */ +function &fn(/* testTypeIntersectionNonArrowFunctionDeclaration */ Foo&Bar $something) {} + +/* testTypeIntersectionWithInvalidTypes */ +function (int&string $var) {}; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +return function( Foo& diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php new file mode 100644 index 000000000..217002193 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/TypeIntersectionTest.php @@ -0,0 +1,138 @@ + + * @author Jaroslav Hanslík + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class TypeIntersectionTest extends AbstractMethodUnitTest +{ + + + /** + * Test that non-intersection type bitwise and tokens are still tokenized as bitwise and. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataBitwiseAnd + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBitwiseAnd($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION]); + $this->assertSame(T_BITWISE_AND, $tokens[$opener]['code']); + $this->assertSame('T_BITWISE_AND', $tokens[$opener]['type']); + + }//end testBitwiseAnd() + + + /** + * Data provider. + * + * @see testBitwiseAnd() + * + * @return array + */ + public function dataBitwiseAnd() + { + return [ + ['/* testBitwiseAnd1 */'], + ['/* testBitwiseAnd2 */'], + ['/* testBitwiseAndPropertyDefaultValue */'], + ['/* testBitwiseAndParamDefaultValue */'], + ['/* testBitwiseAnd3 */'], + ['/* testBitwiseAnd4 */'], + ['/* testBitwiseAnd5 */'], + ['/* testBitwiseAndClosureParamDefault */'], + ['/* testBitwiseAndArrowParamDefault */'], + ['/* testBitwiseAndArrowExpression */'], + ['/* testBitwiseAndInArrayKey */'], + ['/* testBitwiseAndInArrayValue */'], + ['/* testBitwiseAndInShortArrayKey */'], + ['/* testBitwiseAndInShortArrayValue */'], + ['/* testBitwiseAndNonArrowFnFunctionCall */'], + ['/* testBitwiseAnd6 */'], + ['/* testLiveCoding */'], + ]; + + }//end dataBitwiseAnd() + + + /** + * Test that bitwise and tokens when used as part of a intersection type are tokenized as `T_TYPE_INTERSECTION`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataTypeIntersection + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypeIntersection($testMarker) + { + $tokens = self::$phpcsFile->getTokens(); + + $opener = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION]); + $this->assertSame(T_TYPE_INTERSECTION, $tokens[$opener]['code']); + $this->assertSame('T_TYPE_INTERSECTION', $tokens[$opener]['type']); + + }//end testTypeIntersection() + + + /** + * Data provider. + * + * @see testTypeIntersection() + * + * @return array + */ + public function dataTypeIntersection() + { + return [ + ['/* testTypeIntersectionPropertySimple */'], + ['/* testTypeIntersectionPropertyReverseModifierOrder */'], + ['/* testTypeIntersectionPropertyMulti1 */'], + ['/* testTypeIntersectionPropertyMulti2 */'], + ['/* testTypeIntersectionPropertyMulti3 */'], + ['/* testTypeIntersectionPropertyNamespaceRelative */'], + ['/* testTypeIntersectionPropertyPartiallyQualified */'], + ['/* testTypeIntersectionPropertyFullyQualified */'], + ['/* testTypeIntersectionPropertyWithReadOnlyKeyword */'], + ['/* testTypeIntersectionParam1 */'], + ['/* testTypeIntersectionParam2 */'], + ['/* testTypeIntersectionParam3 */'], + ['/* testTypeIntersectionParamNamespaceRelative */'], + ['/* testTypeIntersectionParamPartiallyQualified */'], + ['/* testTypeIntersectionParamFullyQualified */'], + ['/* testTypeIntersectionReturnType */'], + ['/* testTypeIntersectionConstructorPropertyPromotion */'], + ['/* testTypeIntersectionAbstractMethodReturnType1 */'], + ['/* testTypeIntersectionAbstractMethodReturnType2 */'], + ['/* testTypeIntersectionReturnTypeNamespaceRelative */'], + ['/* testTypeIntersectionReturnPartiallyQualified */'], + ['/* testTypeIntersectionReturnFullyQualified */'], + ['/* testTypeIntersectionClosureParamIllegalNullable */'], + ['/* testTypeIntersectionWithReference */'], + ['/* testTypeIntersectionWithSpreadOperator */'], + ['/* testTypeIntersectionClosureReturn */'], + ['/* testTypeIntersectionArrowParam */'], + ['/* testTypeIntersectionArrowReturnType */'], + ['/* testTypeIntersectionNonArrowFunctionDeclaration */'], + ['/* testTypeIntersectionWithInvalidTypes */'], + ]; + + }//end dataTypeIntersection() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc new file mode 100644 index 000000000..540f72c9d --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Core/Tokenizer/UndoNamespacedNameSingleTokenTest.inc @@ -0,0 +1,147 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +class UndoNamespacedNameSingleTokenTest extends AbstractMethodUnitTest +{ + + + /** + * Test that identifier names are tokenized the same across PHP versions, based on the PHP 5/7 tokenization. + * + * @param string $testMarker The comment prefacing the test. + * @param array $expectedTokens The tokenization expected. + * + * @dataProvider dataIdentifierTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testIdentifierTokenization($testMarker, $expectedTokens) + { + $tokens = self::$phpcsFile->getTokens(); + $identifier = $this->getTargetToken($testMarker, constant($expectedTokens[0]['type'])); + + foreach ($expectedTokens as $key => $tokenInfo) { + $this->assertSame(constant($tokenInfo['type']), $tokens[$identifier]['code']); + $this->assertSame($tokenInfo['type'], $tokens[$identifier]['type']); + $this->assertSame($tokenInfo['content'], $tokens[$identifier]['content']); + + ++$identifier; + } + + }//end testIdentifierTokenization() + + + /** + * Data provider. + * + * @see testIdentifierTokenization() + * + * @return array + */ + public function dataIdentifierTokenization() + { + return [ + [ + '/* testNamespaceDeclaration */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Package', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testNamespaceDeclarationWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Domain', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testUseStatementWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Domain', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testFunctionUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testFunctionUseStatementWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_in_ns', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testConstantUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_NAME', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testConstantUseStatementWithLevels */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'OTHER_CONSTANT', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testMultiUseUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'UnqualifiedClassName', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testMultiUsePartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'PartiallyClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testGroupUseStatement */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_OPEN_USE_GROUP', + 'content' => '{', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'AnotherDomain', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_grouped', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_GROUPED', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sub', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'YetAnotherDomain', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevelA', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_grouped_too', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevelB', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_GROUPED_TOO', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_CLOSE_USE_GROUP', + 'content' => '}', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testClassName */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'MyClass', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testExtendedFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'FQN', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testImplementsRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testImplementsFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testImplementsUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Unqualified', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + [ + '/* testImplementsPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Sub', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + [ + '/* testFunctionName */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testTypeDeclarationRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_TYPE_UNION', + 'content' => '|', + ], + [ + 'type' => 'T_STRING', + 'content' => 'object', + ], + ], + ], + [ + '/* testTypeDeclarationFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testTypeDeclarationUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Unqualified', + ], + [ + 'type' => 'T_TYPE_UNION', + 'content' => '|', + ], + [ + 'type' => 'T_FALSE', + 'content' => 'false', + ], + ], + ], + [ + '/* testTypeDeclarationPartiallyQualified */', + [ + [ + 'type' => 'T_NULLABLE', + 'content' => '?', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testReturnTypeFQN */', + [ + [ + 'type' => 'T_NULLABLE', + 'content' => '?', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testFunctionCallRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'NameSpace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testFunctionCallFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Package', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testFunctionCallUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testFunctionPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testCatchRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testCatchFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testCatchUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testCatchPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testNewRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testNewFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testNewUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testNewPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testDoubleColonRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testDoubleColonFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testDoubleColonUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testDoubleColonPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + [ + '/* testInstanceOfRelative */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testInstanceOfFQN */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Full', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_CLOSE_PARENTHESIS', + 'content' => ')', + ], + ], + ], + [ + '/* testInstanceOfUnqualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + [ + '/* testInstanceOfPartiallyQualified */', + [ + [ + 'type' => 'T_STRING', + 'content' => 'Partially', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + [ + '/* testInvalidInPHP8Whitespace */', + [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + [ + '/* testInvalidInPHP8Comments */', + [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat.Sniff -- for reasons +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '/* comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + ]; + + }//end dataIdentifierTokenization() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/FileList.php b/kirki-composer/squizlabs/php_codesniffer/tests/FileList.php new file mode 100644 index 000000000..8ef57b7af --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/FileList.php @@ -0,0 +1,94 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +class FileList +{ + + /** + * The path to the project root directory. + * + * @var string + */ + protected $rootPath; + + /** + * Recursive directory iterator. + * + * @var \DirectoryIterator + */ + public $fileIterator; + + /** + * Base regex to use if no filter regex is provided. + * + * Matches based on: + * - File path starts with the project root (replacement done in constructor). + * - Don't match .git/ files. + * - Don't match dot files, i.e. "." or "..". + * - Don't match backup files. + * - Match everything else in a case-insensitive manner. + * + * @var string + */ + private $baseRegex = '`^%s(?!\.git/)(?!(.*/)?\.+$)(?!.*\.(bak|orig)).*$`Dix'; + + + /** + * Constructor. + * + * @param string $directory The directory to examine. + * @param string $rootPath Path to the project root. + * @param string $filter PCRE regular expression to filter the file list with. + */ + public function __construct($directory, $rootPath='', $filter='') + { + $this->rootPath = $rootPath; + + $directory = new \RecursiveDirectoryIterator( + $directory, + \RecursiveDirectoryIterator::UNIX_PATHS + ); + $flattened = new \RecursiveIteratorIterator( + $directory, + \RecursiveIteratorIterator::LEAVES_ONLY, + \RecursiveIteratorIterator::CATCH_GET_CHILD + ); + + if ($filter === '') { + $filter = sprintf($this->baseRegex, preg_quote($this->rootPath)); + } + + $this->fileIterator = new \RegexIterator($flattened, $filter); + + return $this; + + }//end __construct() + + + /** + * Retrieve the filtered file list as an array. + * + * @return array + */ + public function getList() + { + $fileList = []; + + foreach ($this->fileIterator as $file) { + $fileList[] = str_replace($this->rootPath, '', $file); + } + + return $fileList; + + }//end getList() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php b/kirki-composer/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php new file mode 100644 index 000000000..c050a0c2a --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php @@ -0,0 +1,461 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\LocalFile; +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +abstract class AbstractSniffUnitTest extends TestCase +{ + + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * Overwrite this attribute in a child class of TestCase. + * Setting this attribute in setUp() has no effect! + * + * @var boolean + */ + protected $backupGlobals = false; + + /** + * The path to the standard's main directory. + * + * @var string + */ + public $standardsDir = null; + + /** + * The path to the standard's test directory. + * + * @var string + */ + public $testsDir = null; + + + /** + * Sets up this unit test. + * + * @return void + */ + protected function setUp() + { + $class = get_class($this); + $this->standardsDir = $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$class]; + $this->testsDir = $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$class]; + + }//end setUp() + + + /** + * Get a list of all test files to check. + * + * These will have the same base as the sniff name but different extensions. + * We ignore the .php file as it is the class. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = []; + + $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); + $di = new \DirectoryIterator($dir); + + foreach ($di as $file) { + $path = $file->getPathname(); + if (substr($path, 0, strlen($testFileBase)) === $testFileBase) { + if ($path !== $testFileBase.'php' && substr($path, -5) !== 'fixed' && substr($path, -4) !== '.bak') { + $testFiles[] = $path; + } + } + } + + // Put them in order. + sort($testFiles); + + return $testFiles; + + }//end getTestFiles() + + + /** + * Should this test be skipped for some reason. + * + * @return boolean + */ + protected function shouldSkipTest() + { + return false; + + }//end shouldSkipTest() + + + /** + * Tests the extending classes Sniff class. + * + * @return void + * @throws \PHPUnit\Framework\Exception + */ + final public function testSniff() + { + // Skip this test if we can't run in this environment. + if ($this->shouldSkipTest() === true) { + $this->markTestSkipped(); + } + + $sniffCode = Common::getSniffCode(get_class($this)); + list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); + + $testFileBase = $this->testsDir.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'UnitTest.'; + + // Get a list of all test files to check. + $testFiles = $this->getTestFiles($testFileBase); + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'][] = $testFiles; + + if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG']) === true) { + $config = $GLOBALS['PHP_CODESNIFFER_CONFIG']; + } else { + $config = new Config(); + $config->cache = false; + $GLOBALS['PHP_CODESNIFFER_CONFIG'] = $config; + } + + $config->standards = [$standardName]; + $config->sniffs = [$sniffCode]; + $config->ignored = []; + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS']) === false) { + $GLOBALS['PHP_CODESNIFFER_RULESETS'] = []; + } + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]) === false) { + $ruleset = new Ruleset($config); + $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName] = $ruleset; + } + + $ruleset = $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]; + + $sniffFile = $this->standardsDir.DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'Sniff.php'; + + $sniffClassName = substr(get_class($this), 0, -8).'Sniff'; + $sniffClassName = str_replace('\Tests\\', '\Sniffs\\', $sniffClassName); + $sniffClassName = Common::cleanSniffClass($sniffClassName); + + $restrictions = [strtolower($sniffClassName) => true]; + $ruleset->registerSniffs([$sniffFile], $restrictions, []); + $ruleset->populateTokenListeners(); + + $failureMessages = []; + foreach ($testFiles as $testFile) { + $filename = basename($testFile); + $oldConfig = $config->getSettings(); + + try { + $this->setCliValues($filename, $config); + $phpcsFile = new LocalFile($testFile, $ruleset, $config); + $phpcsFile->process(); + } catch (RuntimeException $e) { + $this->fail('An unexpected exception has been caught: '.$e->getMessage()); + } + + $failures = $this->generateFailureMessages($phpcsFile); + $failureMessages = array_merge($failureMessages, $failures); + + if ($phpcsFile->getFixableCount() > 0) { + // Attempt to fix the errors. + $phpcsFile->fixer->fixFile(); + $fixable = $phpcsFile->getFixableCount(); + if ($fixable > 0) { + $failureMessages[] = "Failed to fix $fixable fixable violations in $filename"; + } + + // Check for a .fixed file to check for accuracy of fixes. + $fixedFile = $testFile.'.fixed'; + if (file_exists($fixedFile) === true) { + $diff = $phpcsFile->fixer->generateDiff($fixedFile); + if (trim($diff) !== '') { + $filename = basename($testFile); + $fixedFilename = basename($fixedFile); + $failureMessages[] = "Fixed version of $filename does not match expected version in $fixedFilename; the diff is\n$diff"; + } + } + } + + // Restore the config. + $config->setSettings($oldConfig); + }//end foreach + + if (empty($failureMessages) === false) { + $this->fail(implode(PHP_EOL, $failureMessages)); + } + + }//end testSniff() + + + /** + * Generate a list of test failures for a given sniffed file. + * + * @param \PHP_CodeSniffer\Files\LocalFile $file The file being tested. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function generateFailureMessages(LocalFile $file) + { + $testFile = $file->getFilename(); + + $foundErrors = $file->getErrors(); + $foundWarnings = $file->getWarnings(); + $expectedErrors = $this->getErrorList(basename($testFile)); + $expectedWarnings = $this->getWarningList(basename($testFile)); + + if (is_array($expectedErrors) === false) { + throw new RuntimeException('getErrorList() must return an array'); + } + + if (is_array($expectedWarnings) === false) { + throw new RuntimeException('getWarningList() must return an array'); + } + + /* + We merge errors and warnings together to make it easier + to iterate over them and produce the errors string. In this way, + we can report on errors and warnings in the same line even though + it's not really structured to allow that. + */ + + $allProblems = []; + $failureMessages = []; + + foreach ($foundErrors as $line => $lineErrors) { + foreach ($lineErrors as $column => $errors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundErrorsTemp = []; + foreach ($allProblems[$line]['found_errors'] as $foundError) { + $foundErrorsTemp[] = $foundError; + } + + $errorsTemp = []; + foreach ($errors as $foundError) { + $errorsTemp[] = $foundError['message'].' ('.$foundError['source'].')'; + + $source = $foundError['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($foundError['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); + }//end foreach + + if (isset($expectedErrors[$line]) === true) { + $allProblems[$line]['expected_errors'] = $expectedErrors[$line]; + } else { + $allProblems[$line]['expected_errors'] = 0; + } + + unset($expectedErrors[$line]); + }//end foreach + + foreach ($expectedErrors as $line => $numErrors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_errors'] = $numErrors; + } + + foreach ($foundWarnings as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $warnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundWarningsTemp = []; + foreach ($allProblems[$line]['found_warnings'] as $foundWarning) { + $foundWarningsTemp[] = $foundWarning; + } + + $warningsTemp = []; + foreach ($warnings as $warning) { + $warningsTemp[] = $warning['message'].' ('.$warning['source'].')'; + + $source = $warning['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($warning['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp); + }//end foreach + + if (isset($expectedWarnings[$line]) === true) { + $allProblems[$line]['expected_warnings'] = $expectedWarnings[$line]; + } else { + $allProblems[$line]['expected_warnings'] = 0; + } + + unset($expectedWarnings[$line]); + }//end foreach + + foreach ($expectedWarnings as $line => $numWarnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_warnings'] = $numWarnings; + } + + // Order the messages by line number. + ksort($allProblems); + + foreach ($allProblems as $line => $problems) { + $numErrors = count($problems['found_errors']); + $numWarnings = count($problems['found_warnings']); + $expectedErrors = $problems['expected_errors']; + $expectedWarnings = $problems['expected_warnings']; + + $errors = ''; + $foundString = ''; + + if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) { + $lineMessage = "[LINE $line]"; + $expectedMessage = 'Expected '; + $foundMessage = 'in '.basename($testFile).' but found '; + + if ($expectedErrors !== $numErrors) { + $expectedMessage .= "$expectedErrors error(s)"; + $foundMessage .= "$numErrors error(s)"; + if ($numErrors !== 0) { + $foundString .= 'error(s)'; + $errors .= implode(PHP_EOL.' -> ', $problems['found_errors']); + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= ' and '; + $foundMessage .= ' and '; + if ($numWarnings !== 0) { + if ($foundString !== '') { + $foundString .= ' and '; + } + } + } + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= "$expectedWarnings warning(s)"; + $foundMessage .= "$numWarnings warning(s)"; + if ($numWarnings !== 0) { + $foundString .= 'warning(s)'; + if (empty($errors) === false) { + $errors .= PHP_EOL.' -> '; + } + + $errors .= implode(PHP_EOL.' -> ', $problems['found_warnings']); + } + } + + $fullMessage = "$lineMessage $expectedMessage $foundMessage."; + if ($errors !== '') { + $fullMessage .= " The $foundString found were:".PHP_EOL." -> $errors"; + } + + $failureMessages[] = $fullMessage; + }//end if + }//end foreach + + return $failureMessages; + + }//end generateFailureMessages() + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $filename The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function setCliValues($filename, $config) + { + return; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + abstract protected function getErrorList(); + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + abstract protected function getWarningList(); + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php b/kirki-composer/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php new file mode 100644 index 000000000..24527dd51 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php @@ -0,0 +1,123 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use PHP_CodeSniffer\Util\Standards; +use PHP_CodeSniffer\Autoload; +use PHPUnit\TextUI\TestRunner; +use PHPUnit\Framework\TestSuite; + +class AllSniffs +{ + + + /** + * Prepare the test runner. + * + * @return void + */ + public static function main() + { + TestRunner::run(self::suite()); + + }//end main() + + + /** + * Add all sniff unit tests into a test suite. + * + * Sniff unit tests are found by recursing through the 'Tests' directory + * of each installed coding standard. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = []; + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = []; + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'] = []; + + $suite = new TestSuite('PHP CodeSniffer Standards'); + + $isInstalled = !is_file(__DIR__.'/../../autoload.php'); + + // Optionally allow for ignoring the tests for one or more standards. + $ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS'); + if ($ignoreTestsForStandards === false) { + $ignoreTestsForStandards = []; + } else { + $ignoreTestsForStandards = explode(',', $ignoreTestsForStandards); + } + + $installedStandards = self::getInstalledStandardDetails(); + + foreach ($installedStandards as $standard => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + + // If the test is running PEAR installed, the built-in standards + // are split into different directories; one for the sniffs and + // a different file system location for tests. + if ($isInstalled === true && is_dir(dirname($details['path']).DIRECTORY_SEPARATOR.'Generic') === true) { + $testPath = realpath(__DIR__.'/../../src/Standards/'.$standard); + } else { + $testPath = $details['path']; + } + + if (in_array($standard, $ignoreTestsForStandards, true) === true) { + continue; + } + + $testsDir = $testPath.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR; + if (is_dir($testsDir) === false) { + // No tests for this standard. + continue; + } + + $di = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($testsDir)); + + foreach ($di as $file) { + // Skip hidden files. + if (substr($file->getFilename(), 0, 1) === '.') { + continue; + } + + // Tests must have the extension 'php'. + $parts = explode('.', $file); + $ext = array_pop($parts); + if ($ext !== 'php') { + continue; + } + + $className = Autoload::loadFile($file->getPathname()); + $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$className] = $details['path']; + $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$className] = $testsDir; + $suite->addTestSuite($className); + } + }//end foreach + + return $suite; + + }//end suite() + + + /** + * Get the details of all coding standards installed. + * + * @return array + * @see Standards::getInstalledStandardDetails() + */ + protected static function getInstalledStandardDetails() + { + return Standards::getInstalledStandardDetails(true); + + }//end getInstalledStandardDetails() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/TestSuite.php b/kirki-composer/squizlabs/php_codesniffer/tests/TestSuite.php new file mode 100644 index 000000000..9eb269f8b --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/TestSuite.php @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; +use PHPUnit\Framework\TestResult; + +class TestSuite extends PHPUnit_TestSuite +{ + + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param \PHPUnit\Framework\TestResult $result A test result. + * + * @return \PHPUnit\Framework\TestResult + */ + public function run(TestResult $result=null) + { + $result = parent::run($result); + printPHPCodeSnifferTestOutput(); + return $result; + + }//end run() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/TestSuite7.php b/kirki-composer/squizlabs/php_codesniffer/tests/TestSuite7.php new file mode 100644 index 000000000..43db293d5 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/TestSuite7.php @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; +use PHPUnit\Framework\TestResult; + +class TestSuite extends PHPUnit_TestSuite +{ + + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param \PHPUnit\Framework\TestResult $result A test result. + * + * @return \PHPUnit\Framework\TestResult + */ + public function run(TestResult $result=null): TestResult + { + $result = parent::run($result); + printPHPCodeSnifferTestOutput(); + return $result; + + }//end run() + + +}//end class diff --git a/kirki-composer/squizlabs/php_codesniffer/tests/bootstrap.php b/kirki-composer/squizlabs/php_codesniffer/tests/bootstrap.php new file mode 100644 index 000000000..47084d113 --- /dev/null +++ b/kirki-composer/squizlabs/php_codesniffer/tests/bootstrap.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + define('PHP_CODESNIFFER_IN_TESTS', true); +} + +if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); +} + +if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', 0); +} + +if (is_file(__DIR__.'/../autoload.php') === true) { + include_once __DIR__.'/../autoload.php'; +} else { + include_once 'PHP/CodeSniffer/autoload.php'; +} + +$tokens = new \PHP_CodeSniffer\Util\Tokens(); + +// Compatibility for PHPUnit < 6 and PHPUnit 6+. +if (class_exists('PHPUnit_Framework_TestSuite') === true && class_exists('PHPUnit\Framework\TestSuite') === false) { + class_alias('PHPUnit_Framework_TestSuite', 'PHPUnit'.'\Framework\TestSuite'); +} + +if (class_exists('PHPUnit_Framework_TestCase') === true && class_exists('PHPUnit\Framework\TestCase') === false) { + class_alias('PHPUnit_Framework_TestCase', 'PHPUnit'.'\Framework\TestCase'); +} + +if (class_exists('PHPUnit_TextUI_TestRunner') === true && class_exists('PHPUnit\TextUI\TestRunner') === false) { + class_alias('PHPUnit_TextUI_TestRunner', 'PHPUnit'.'\TextUI\TestRunner'); +} + +if (class_exists('PHPUnit_Framework_TestResult') === true && class_exists('PHPUnit\Framework\TestResult') === false) { + class_alias('PHPUnit_Framework_TestResult', 'PHPUnit'.'\Framework\TestResult'); +} + +// Determine whether this is a PEAR install or not. +$GLOBALS['PHP_CODESNIFFER_PEAR'] = false; + +if (is_file(__DIR__.'/../autoload.php') === false) { + $GLOBALS['PHP_CODESNIFFER_PEAR'] = true; +} + + +/** + * A global util function to help print unit test fixing data. + * + * @return void + */ +function printPHPCodeSnifferTestOutput() +{ + echo PHP_EOL.PHP_EOL; + + $output = 'The test files'; + $data = []; + + $codeCount = count($GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']); + if (empty($GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']) === false) { + $files = call_user_func_array('array_merge', $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']); + $files = array_unique($files); + $fileCount = count($files); + + $output = '%d sniff test files'; + $data[] = $fileCount; + } + + $output .= ' generated %d unique error codes'; + $data[] = $codeCount; + + if ($codeCount > 0) { + $fixes = count($GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']); + $percent = round(($fixes / $codeCount * 100), 2); + + $output .= '; %d were fixable (%d%%)'; + $data[] = $fixes; + $data[] = $percent; + } + + vprintf($output, $data); + +}//end printPHPCodeSnifferTestOutput() diff --git a/kirki-composer/wp-coding-standards/wpcs/.gitattributes b/kirki-composer/wp-coding-standards/wpcs/.gitattributes new file mode 100644 index 000000000..c12f94cfb --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/.gitattributes @@ -0,0 +1,25 @@ +# +# Exclude these files from release archives. +# This will also make them unavailable when using Composer with `--prefer-dist`. +# If you develop for WPCS using Composer, use `--prefer-source`. +# https://blog.madewithlove.be/post/gitattributes/ +# +/.travis.yml export-ignore +/.phpcs.xml.dist export-ignore +/phpunit.xml.dist export-ignore +/.github export-ignore +/bin export-ignore +/WordPress/Tests export-ignore + +# +# Auto detect text files and perform LF normalization +# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ +# +* text=auto + +# +# The above will handle all files NOT found below +# +*.md text +*.php text +*.inc text diff --git a/kirki-composer/wp-coding-standards/wpcs/.gitignore b/kirki-composer/wp-coding-standards/wpcs/.gitignore new file mode 100644 index 000000000..bfec4c3c3 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/.gitignore @@ -0,0 +1,5 @@ +vendor +composer.lock +phpunit.xml +phpcs.xml +.phpcs.xml diff --git a/kirki-composer/wp-coding-standards/wpcs/CHANGELOG.md b/kirki-composer/wp-coding-standards/wpcs/CHANGELOG.md new file mode 100644 index 000000000..f8c8c9878 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/CHANGELOG.md @@ -0,0 +1,1208 @@ +# Change Log for WordPress Coding Standards + +All notable changes to this project will be documented in this file. + +This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a CHANGELOG](https://keepachangelog.com/). + +## [Unreleased] + +_No documentation available about unreleased changes as of yet._ + +## [2.3.0] - 2020-05-14 + +### Added +- The `WordPress.WP.I18n` sniff contains a new check for translatable text strings which are wrapped in HTML tags, like `

    Translate me

    `. Those tags should be moved out of the translatable string. + Note: Translatable strings wrapped in `
    ` tags where the URL is intended to be localized will not trigger this check. + +### Changed +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `5.1`. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.4. +- Improved grammar of an error message in the `WordPress.WP.DiscouragedFunctions` sniff. +- CI: The codebase is now - preliminary - being tested against the PHPCS 4.x development branch. + +### Fixed +- All function call detection sniffs: fixed a bug where constants with the same name as one of the targeted functions could inadvertently be recognized as if they were a called function. +- `WordPress.DB.PreparedSQL`: fixed a bug where the sniff would trigger on the namespace separator character `\\`. +- `WordPress.Security.EscapeOutput`: fixed a bug with the variable replacement in one of the error messages. + + +## [2.2.1] - 2020-02-04 + +### Added +- Metrics to the `WordPress.Arrays.CommaAfterArrayItem` sniff. These can be displayed using `--report=info`. +- The `sanitize_hex_color()` and the `sanitize_hex_color_no_hash()` functions to the `escapingFunctions` list used by the `WordPress.Security.EscapeOutput` sniff. + +### Changed +- The recommended version of the suggested DealerDirect PHPCS Composer plugin is now `^0.6`. + +### Fixed +- `WordPress.PHP.NoSilencedErrors`: depending on the custom properties set, the metrics would be different. +- `WordPress.WhiteSpace.ControlStructureSpacing`: fixed undefined index notice for closures with `use`. +- `WordPress.WP.GlobalVariablesOverride`: fixed undefined offset notice when the `treat_files_as_scoped` property would be set to `true`. +- `WordPress.WP.I18n`: fixed a _Trying to access array offset on value of type null_ error when the sniff was run on PHP 7.4 and would encounter a translation function expecting singular and plural texts for which one of these arguments was missing. + +## [2.2.0] - 2019-11-11 + +Note: The repository has moved. The new URL is https://github.com/WordPress/WordPress-Coding-Standards. +The move does not affect the package name for Packagist. This remains the same: `wp-coding-standards/wpcs`. + +### Added +- New `WordPress.DateTime.CurrentTimeTimestamp` sniff to the `WordPress-Core` ruleset, which checks against the use of the WP native `current_time()` function to retrieve a timestamp as this won't be a _real_ timestamp. Includes an auto-fixer. +- New `WordPress.DateTime.RestrictedFunctions` sniff to the `WordPress-Core` ruleset, which checks for the use of certain date/time related functions. Initially this sniff forbids the use of the PHP native `date_default_timezone_set()` and `date()` functions. +- New `WordPress.PHP.DisallowShortTernary` sniff to the `WordPress-Core` ruleset, which, as the name implies, disallows the use of short ternaries. +- New `WordPress.CodeAnalysis.EscapedNotTranslated` sniff to the `WordPress-Extra` ruleset which will warn when a text string is escaped for output, but not being translated, while the arguments passed to the function call give the impression that translation is intended. +- New `WordPress.NamingConventions.ValidPostTypeSlug` sniff to the `WordPress-Extra` ruleset which will examine calls to `register_post_type()` and throw errors when an invalid post type slug is used. +- `Generic.Arrays.DisallowShortArraySyntax` to the `WordPress-Core` ruleset. +- `WordPress.NamingConventions.PrefixAllGlobals`: the `PHP` prefix has been added to the prefix blacklist as it is reserved by PHP itself. +- The `wp_sanitize_redirect()` function to the `sanitizingFunctions` list used by the `WordPress.Security.NonceVerification`, `WordPress.Security.ValidatedSanitizedInput` and `WordPress.Security.EscapeOutput` sniffs. +- The `sanitize_key()` and the `highlight_string()` functions to the `escapingFunctions` list used by the `WordPress.Security.EscapeOutput` sniff. +- The `RECOVERY_MODE_COOKIE` constant to the list of WP Core constants which may be defined by plugins and themes and therefore don't need to be prefixed (`WordPress.NamingConventions.PrefixAllGlobals`). +- `$content_width`, `$plugin`, `$mu_plugin` and `$network_plugin` to the list of WP globals which is used by both the `WordPress.Variables.GlobalVariables` and the `WordPress.NamingConventions.PrefixAllGlobals` sniffs. +- `Sniff::is_short_list()` utility method to determine whether a _short array_ open/close token actually represents a PHP 7.1+ short list. +- `Sniff::find_list_open_close()` utility method to find the opener and closer for `list()` constructs, including short lists. +- `Sniff::get_list_variables()` utility method which will retrieve an array with the token pointers to the variables which are being assigned to in a `list()` construct. Includes support for short lists. +- `Sniff::is_function_deprecated()` static utility method to determine whether a declared function has been marked as deprecated in the function DocBlock. +- End-user documentation to the following existing sniffs: `WordPress.Arrays.ArrayIndentation`, `WordPress.Arrays.ArrayKeySpacingRestrictions`, `WordPress.Arrays.MultipleStatementAlignment`, `WordPress.Classes.ClassInstantiation`, `WordPress.NamingConventions.ValidHookName`, `WordPress.PHP.IniSet`, `WordPress.Security.SafeRedirect`, `WordPress.WhiteSpace.CastStructureSpacing`, `WordPress.WhiteSpace.DisallowInlineTabs`, `WordPress.WhiteSpace.PrecisionAlignment`, `WordPress.WP.CronInterval`, `WordPress.WP.DeprecatedClasses`, `WordPress.WP.DeprecatedFunctions`, `WordPress.WP.DeprecatedParameters`, `WordPress.WP.DeprecatedParameterValues`, `WordPress.WP.EnqueuedResources`, `WordPress.WP.PostsPerPage`. + This documentation can be exposed via the [`PHP_CodeSniffer` `--generator=...` command-line argument](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage). + +### Changed +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `5.0`. +- The `WordPress.Arrays.ArrayKeySpacingRestrictions` sniff has two new error codes: `TooMuchSpaceBeforeKey` and `TooMuchSpaceAfterKey`. Both auto-fixable. + The sniff will now check that there is _exactly_ one space on the inside of the square brackets around the array key for non-string, non-numeric array keys. Previously, it only checked that there was whitespace, not how much whitespace. +- `WordPress.Arrays.ArrayKeySpacingRestrictions`: the fixers have been made more efficient and less fixer-conflict prone. +- `WordPress.NamingConventions.PrefixAllGlobals`: plugin/theme prefixes should be at least three characters long. A new `ShortPrefixPassed` error has been added for when the prefix passed does not comply with this rule. +- `WordPress.WhiteSpace.CastStructureSpacing` now allows for no whitespace before a cast when the cast is preceded by the spread `...` operator. This pre-empts a fixer conflict for when the spacing around the spread operator will start to get checked. +- The `WordPress.WP.DeprecatedClasses` sniff will now detect classes deprecated in WP 4.9 and WP 5.3. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.3. +- `WordPress.NamingConventions.ValidHookName` now has "cleaner" error messages and higher precision for the line on which an error is thrown. +- `WordPress.Security.EscapeOutput`: if an error refers to array access via a variable, the array index key will now be included in the error message. +- The processing of the `WordPress` ruleset by `PHP_CodeSniffer` will now be faster. +- Various minor code tweaks and clean up. +- Various minor documentation fixes. +- Documentation: updated the repo URL in all relevant places. + +### Deprecated +- The `WordPress.WP.TimezoneChange` sniff. Use the `WordPress.DateTime.RestrictedFunctions` instead. + The deprecated sniff will be removed in WPCS 3.0.0. + +### Fixed +- All sniffs in the `WordPress.Arrays` category will no longer treat _short lists_ as if they were a short array. +- The `WordPress.NamingConventions.ValidFunctionName` and the `WordPress.NamingConventions.PrefixAllGlobals` sniff will now ignore functions marked as `@deprecated`. +- Both the `WordPress.NamingConventions.PrefixAllGlobals` sniff as well as the `WordPress.WP.GlobalVariablesOverride` sniff have been updated to recognize variables being declared via (long/short) `list()` constructs and handle them correctly. +- Both the `WordPress.NamingConventions.PrefixAllGlobals` sniff as well as the `WordPress.WP.GlobalVariablesOverride` sniff will now take a limited list of WP global variables _which are intended to be overwritten by plugins/themes_ into account. + Initially this list contains the `$content_width` and the `$wp_cockneyreplace` variables. +- `WordPress.NamingConventions.ValidHookName`: will no longer examine a string array access index key as if it were a part of the hook name. +- `WordPress.Security.EscapeOutput`: will no longer trigger on the typical `basename( __FILE__ )` pattern if found as the first parameter passed to a call to `_deprecated_file()`. +- `WordPress.WP.CapitalPDangit`: now allows for the `.test` TLD in URLs. +- WPCS is now fully compatible with PHP 7.4. + Note: `PHP_CodeSniffer` itself is only compatible with PHP 7.4 from PHPCS 3.5.0 onwards. + + +## [2.1.1] - 2019-05-21 + +### Changed +- The `WordPress.WP.CapitalPDangit` will now ignore misspelled instances of `WordPress` within constant declarations. + This covers both constants declared using `defined()` as well as constants declared using the `const` keyword. +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.9`. + +### Removed +- `paginate_comments_links()` from the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. + This affects the `WordPress.Security.EscapeOutput` sniff. + +### Fixed +- The `$current_blog` and `$tag_ID` variables have been added to the list of WordPress global variables. + This fixes some false positives from the `WordPress.NamingConventions.PrefixAllGlobals` and the `WordPress.WP.GlobalVariablesOverride` sniffs. +- The generic `TestCase` class name has been added to the `$test_class_whitelist`. + This fixes some false positives from the `WordPress.NamingConventions.FileName`, `WordPress.NamingConventions.PrefixAllGlobals` and the `WordPress.WP.GlobalVariablesOverride` sniffs. +- The `WordPress.NamingConventions.ValidVariableName` sniff will now correctly recognize `$tag_ID` as a WordPress native, mixed-case variable. +- The `WordPress.Security.NonceVerification` sniff will now correctly recognize nonce verification within a nested closure or anonymous class. + + +## [2.1.0] - 2019-04-08 + +### Added +- New `WordPress.PHP.IniSet` sniff to the `WordPress-Extra` ruleset. + This sniff will detect calls to `ini_set()` and `ini_alter()` and warn against their use as changing configuration values at runtime leads to an unpredictable runtime environment, which can result in conflicts between core/plugins/themes. + - The sniff will not throw notices about a very limited set of "safe" ini directives. + - For a number of ini directives for which there are alternative, non-conflicting ways to achieve the same available, the sniff will throw an `error` and advise using the alternative. +- `doubleval()`, `count()` and `sizeof()` to `Sniff::$unslashingSanitizingFunctions` property. + While `count()` and its alias `sizeof()`, don't actually unslash or sanitize, the output of these functions is safe to use without unslashing or sanitizing. + This affects the `WordPress.Security.ValidatedSanitizedInput` and the `WordPress.Security.NonceVerification` sniffs. +- The new WP 5.1 `WP_UnitTestCase_Base` class to the `Sniff::$test_class_whitelist` property. +- New `Sniff::get_array_access_keys()` utility method to retrieve all array keys for a variable using multi-level array access. +- New `Sniff::is_class_object_call()`, `Sniff::is_token_namespaced()` utility methods. + These should help make the checking of whether or not a function call is a global function, method call or a namespaced function call more consistent. + This also implements allowing for the [namespace keyword being used as an operator](https://www.php.net/manual/en/language.namespaces.nsconstants.php#example-258). +- New `Sniff::is_in_function_call()` utility method to facilitate checking whether a token is (part of) a parameter passed to a specific (set of) function(s). +- New `Sniff::is_in_type_test()` utility method to determine if a variable is being type tested, along with a `Sniff::$typeTestFunctions` property containing the names of the functions this applies to. +- New `Sniff::is_in_array_comparison()` utility method to determine if a variable is (part of) a parameter in an array-value comparison, along with a `Sniff::$arrayCompareFunctions` property containing the names of the relevant functions. +- New `Sniff::$arrayWalkingFunctions` property containing the names of array functions which apply a callback to the array, but don't change the array by reference. +- New `Sniff::$unslashingFunctions` property containing the names of functions which unslash data passed to them and return the unslashed result. + +### Changed +- Moved the `WordPress.PHP.StrictComparisons`, `WordPress.PHP.StrictInArray` and the `WordPress.CodeAnalysis.AssignmentInCondition` sniff from the `WordPress-Extra` to the `WordPress-Core` ruleset. +- The `Squiz.Commenting.InlineComment.SpacingAfter` error is no longer included in the `WordPress-Docs` ruleset. +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.8`. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.1. +- The `WordPress.Security.NonceVerification` sniff now allows for variable type testing, comparisons, unslashing and sanitization before the nonce check. A nonce check within the same scope, however, is still required. +- The `WordPress.Security.ValidatedSanitizedInput` sniff now allows for using a superglobal in an array-value comparison without sanitization, same as when the superglobal is used in a scalar value comparison. +- `WordPress.NamingConventions.PrefixAllGlobals`: some of the error messages have been made more explicit. +- The error messages for the `WordPress.Security.ValidatedSanitizedInput` sniff will now contain information on the index keys accessed. +- The error message for the `WordPress.Security.ValidatedSanitizedInput.InputNotValidated` has been reworded to make it more obvious what the actual issue being reported is. +- The error message for the `WordPress.Security.ValidatedSanitizedInput.MissingUnslash` has been reworded. +- The `Sniff::is_comparison()` method now has a new `$include_coalesce` parameter to allow for toggling whether the null coalesce operator should be seen as a comparison operator. Defaults to `true`. +- All sniffs are now also being tested against PHP 7.4 (unstable) for consistent sniff results. +- The recommended version of the suggested DealerDirect PHPCS Composer plugin is now `^0.5.0`. +- Various minor code tweaks and clean up. + +### Removed +- `ini_set` and `ini_alter` from the list of functions detected by the `WordPress.PHP.DiscouragedFunctions` sniff. + These are now covered via the new `WordPress.PHP.IniSet` sniff. +- `in_array()` and `array_key_exists()` from the list of `Sniff::$sanitizingFunctions`. These are now handled differently. + +### Fixed +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff would underreport when global functions would be autoloaded via a Composer autoload `files` configuration. +- The `WordPress.Security.EscapeOutput` sniff will now recognize `map_deep()` for escaping the values in an array via a callback to an output escaping function. This should prevent false positives. +- The `WordPress.Security.NonceVerification` sniff will no longer inadvertently allow for a variable to be sanitized without a nonce check within the same scope. +- The `WordPress.Security.ValidatedSanitizedInput` sniff will no longer throw errors when a variable is only being type tested. +- The `WordPress.Security.ValidatedSanitizedInput` sniff will now correctly recognize the null coalesce (PHP 7.0) and null coalesce equal (PHP 7.4) operators and will now throw errors for missing unslashing and sanitization where relevant. +- The `WordPress.WP.AlternativeFunctions` sniff will no longer recommend using the WP_FileSystem when PHP native input streams, like `php://input`, or the PHP input stream constants are being read or written to. +- The `WordPress.WP.AlternativeFunctions` sniff will no longer report on usage of the `curl_version()` function. +- The `WordPress.WP.CronInterval` sniff now has improved function recognition which should lower the chance of false positives. +- The `WordPress.WP.EnqueuedResources` sniff will no longer throw false positives for inline jQuery code trying to access a stylesheet link tag. +- Various bugfixes for the `Sniff::has_nonce_check()` method: + - The method will no longer incorrectly identify methods/namespaced functions mirroring the name of WP native nonce verification functions as if they were the global functions. + This will prevent some false negatives. + - The method will now skip over nested closed scopes, such as closures and anonymous classes. This should prevent some false negatives for nonce verification being done while not in the correct scope. + + These fixes affect the `WordPress.Security.NonceVerification` sniff. +- The `Sniff::is_in_isset_or_empty()` method now also checks for usage of `array_key_exist()` and `key_exists()` and will regard these as correct ways to validate a variable. + This should prevent false positives for the `WordPress.Security.ValidatedSanitizedInput` and the `WordPress.Security.NonceVerification` sniffs. +- Various bugfixes for the `Sniff::is_sanitized()` method: + - The method presumed the WordPress coding style regarding code layout, which could lead to false positives. + - The method will no longer incorrectly identify methods/namespaced functions mirroring the name of WP/PHP native unslashing/sanitization functions as if they were the global functions. + This will prevent some false negatives. + - The method will now recognize `map_deep()` for sanitizing an array via a callback to a sanitization function. This should prevent false positives. + - The method will now recognize `stripslashes_deep()` and `stripslashes_from_strings_only()` as valid unslashing functions. This should prevent false positives. + All these fixes affect both the `WordPress.Security.ValidatedSanitizedInput` and the `WordPress.Security.NonceVerification` sniff. +- Various bugfixes for the `Sniff::is_validated()` method: + - The method did not verify correctly whether a variable being validated was the same variable as later used which could lead to false negatives. + - The method did not verify correctly whether a variable being validated had the same array index keys as the variable as later used which could lead to both false negatives as well as false positives. + - The method now also checks for usage of `array_key_exist()` and `key_exists()` and will regard these as correct ways to validate a variable. This should prevent some false positives. + - The methods will now recognize the null coalesce and the null coalesce equal operators as ways to validate a variable. This prevents some false positives. + The results from the `WordPress.Security.ValidatedSanitizedInput` sniff should be more accurate because of these fixes. +- A potential "Undefined index" notice from the `Sniff::is_assignment()` method. + + +## [2.0.0] - 2019-01-16 + +### Important information about this release: + +WordPressCS 2.0.0 contains breaking changes, both for people using custom rulesets as well as for sniff developers who maintain a custom PHPCS standard based on WordPressCS. + +Support for `PHP_CodeSniffer` 2.x has been dropped, the new minimum `PHP_CodeSniffer` version is 3.3.1. +Also, all previously deprecated sniffs, properties and methods have been removed. + +Please read the complete changelog carefully before you upgrade. + +If you are a maintainer of an external standard based on WordPressCS and any of your custom sniffs are based on or extend WPCS sniffs, please read the [Developers Upgrade Guide to WordPressCS 2.0.0](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Upgrade-Guide-to-WordPressCS-2.0.0-for-Developers-of-external-standards). + +### Changes since 2.0.0-RC1 + +#### Fixed + +- `WordPress-Extra`: Reverted back to including the `Squiz.WhiteSpace.LanguageConstructSpacing` sniff instead of the new `Generic.WhiteSpace.LanguageConstructSpacing` sniff as the new sniff is not (yet) available when the PEAR install of PHPCS is used. + +### Changes since 1.2.1 +For a full list of changes from the 1.2.1 version, please review the following changelog: +* https://github.com/WordPress/WordPress-Coding-Standards/releases/tag/2.0.0-RC1 + + +## [2.0.0-RC1] - 2018-12-31 + +### Important information about this release: + +This is the first release candidate for WordPressCS 2.0.0. +WordPressCS 2.0.0 contains breaking changes, both for people using custom rulesets as well as for sniff developers who maintain a custom PHPCS standard based on WordPressCS. + +Support for `PHP_CodeSniffer` 2.x has been dropped, the new minimum `PHP_CodeSniffer` version is 3.3.1. +Also, all previously deprecated sniffs, properties and methods have been removed. + +Please read the complete changelog carefully before you upgrade. + +If you are a maintainer of an external standard based on WordPressCS and any of your custom sniffs are based on or extend WPCS sniffs, please read the [Developers Upgrade Guide to WordPressCS 2.0.0](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Upgrade-Guide-to-WordPressCS-2.0.0-for-Developers-of-external-standards). + +### Added +- `Generic.PHP.DiscourageGoto`, `Generic.PHP.LowerCaseType`, `Generic.WhiteSpace.ArbitraryParenthesesSpacing` and `PSR12.Keywords.ShortFormTypeKeywords` to the `WordPress-Core` ruleset. +- Checking the spacing around the `instanceof` operator to the `WordPress.WhiteSpace.OperatorSpacing` sniff. + +### Changed +- The minimum required `PHP_CodeSniffer` version to 3.3.1 (was 2.9.0). +- The namespace used by WordPressCS has been changed from `WordPress` to `WordPressCS\WordPress`. + This was not possible while `PHP_CodeSniffer` 2.x was still supported, but WordPressCS, as a good Open Source citizen, does not want to occupy the `WordPress` namespace and is releasing its use of it now this is viable. +- The `WordPress.DB.PreparedSQL` sniff used the same error code for two different errors. + The `NotPrepared` error code remains, however an additional `InterpolatedNotPrepared` error code has been added for the second error. + If you are referencing the old error code in a ruleset XML file or in inline annotations, you may need to update it. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff used the same error code for some errors as well as warnings. + The `NonPrefixedConstantFound` error code remains for the related error, but the warning will now use the new `VariableConstantNameFound` error code. + The `NonPrefixedHooknameFound` error code remains for the related error, but the warning will now use the new `DynamicHooknameFound` error code. + If you are referencing the old error codes in a ruleset XML file or in inline annotations, you may need to update these to use the new codes instead. +- `WordPress.NamingConventions.ValidVariableName`: the error messages and error codes used by this sniff have been changed for improved usability and consistency. + - The error messages will now show a suggestion for a valid alternative name for the variable. + - The `NotSnakeCaseMemberVar` error code has been renamed to `UsedPropertyNotSnakeCase`. + - The `NotSnakeCase` error code has been renamed to `VariableNotSnakeCase`. + - The `MemberNotSnakeCase` error code has been renamed to `PropertyNotSnakeCase`. + - The `StringNotSnakeCase` error code has been renamed to `InterpolatedVariableNotSnakeCase`. + If you are referencing the old error codes in a ruleset XML file or in inline annotations, you may need to update these to use the new codes instead. +- The `WordPress.Security.NonceVerification` sniff used the same error code for both an error as well as a warning. + The old error code `NoNonceVerification` is no longer used. + The `error` now uses the `Missing` error code, while the `warning` now uses the `Recommended` error code. + If you are referencing the old error code in a ruleset XML file or in inline annotations, please update these to use the new codes instead. +- The `WordPress.WP.DiscouragedConstants` sniff used to have two error codes `UsageFound` and `DeclarationFound`. + These error codes will now be prefixed by the name of the constant found to allow for more fine-grained excluding/ignoring of warnings generated by this sniff. + If you are referencing the old error codes in a ruleset XML file or in inline annotations, you may need to update these to use the new codes instead. +- The `WordPress.WP.GlobalVariablesOverride.OverrideProhibited` error code has been replaced by the `WordPress.WP.GlobalVariablesOverride.Prohibited` error code. + If you are referencing the old error code in a ruleset XML file or in inline annotations, you may need to update it. +- `WordPress-Extra`: Replaced the inclusion of the `Generic.Files.OneClassPerFile`, `Generic.Files.OneInterfacePerFile` and the `Generic.Files.OneTraitPerFile` sniffs with the new `Generic.Files.OneObjectStructurePerFile` sniff. +- `WordPress-Extra`: Replaced the inclusion of the `Squiz.WhiteSpace.LanguageConstructSpacing` sniff with the new `Generic.WhiteSpace.LanguageConstructSpacing` sniff. +- `WordPress-Extra`: Replaced the inclusion of the `Squiz.Scope.MemberVarScope` sniff with the more comprehensive `PSR2.Classes.PropertyDeclaration` sniff. +- `WordPress.NamingConventions.ValidFunctionName`: Added a unit test confirming support for interfaces extending multiple interfaces. +- `WordPress.NamingConventions.ValidVariableName`: Added unit tests confirming support for multi-variable/property declarations. +- The `get_name_suggestion()` method has been moved from the `WordPress.NamingConventions.ValidFunctionName` sniff to the base `Sniff` class, renamed to `get_snake_case_name_suggestion()` and made static. +- The rulesets are now validated against the `PHP_CodeSniffer` XSD schema. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) to use the recommended ruleset syntax for `PHP_CodeSniffer` 3.3.1+, including using the new [array property format](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.3.0) which is now supported. +- Dev: The command to run the unit tests has changed. Please see the updated instructions in the [CONTRIBUTING.md](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/.github/CONTRIBUTING.md) file. + The `bin/pre-commit` example git hook has been updated to match. Additionally a `run-tests` script has been added to the `composer.json` file for your convenience. + To facilitate this, PHPUnit has been added to `require-dev`, even though it is strictly speaking a dependency of PHPCS, not of WPCS. +- Dev: The DealerDirect PHPCS Composer plugin has been added to `require-dev`. +- Various code tweaks and clean up. +- User facing documentation, including the wiki, as well as inline documentation has been updated for all the changes contained in WordPressCS 2.0 and other recommended best practices for `PHP_CodeSniffer` 3.3.1+. + +### Deprecated +- The use of the [WordPressCS native whitelist comments](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors), which were introduced in WPCS 0.4.0, have been deprecated and support will be removed in WPCS 3.0.0. + The WordPressCS native whitelist comments will continue to work for now, but a deprecation warning will be thrown when they are encountered. + You are encouraged to upgrade our whitelist comment to use the [PHPCS native selective ignore annotations](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.2.0) as introduced in `PHP_CodeSniffer` 3.2.0, as soon as possible. + +### Removed +- Support for PHP 5.3. PHP 5.4 is the minimum requirement for `PHP_CodeSniffer` 3.x. + Includes removing any and all workarounds which were in place to still support PHP 5.3. +- Support for `PHP_CodeSniffer` < 3.3.1. + Includes removing any and all workarounds which were in place for supporting older `PHP_CodeSniffer` versions. +- The `WordPress-VIP` standard which was deprecated since WordPressCS 1.0.0. + For checking a theme/plugin for hosting on the WordPress.com VIP platform, please use the [Automattic VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) instead. +- Support for array properties set in a custom ruleset without the `type="array"` attribute. + Support for this was deprecated in WPCS 1.0.0. + If in doubt about how properties should be set in your custom ruleset, please refer to the [Customizable sniff properties](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties) wiki page which contains XML code examples for setting each and every WPCS native sniff property. + As the minimum `PHP_CodeSniffer` version is now 3.3.1, you can now also use the [new format for setting array properties](https://github.com/squizlabs/PHP_CodeSniffer/releases/tag/3.3.0), so this would be a great moment to review and update your custom ruleset. + Note: the ability to set select properties from the command-line as comma-delimited strings is _not_ affected by this change. +- The following sniffs have been removed outright without deprecation. + If you are referencing these sniffs in a ruleset XML file or in inline annotations, please update these to reference the replacement sniffs instead. + - `WordPress.Functions.FunctionCallSignatureNoParams` - superseded by a bug fix in the upstream `PEAR.Functions.FunctionCallSignature` sniff. + - `WordPress.PHP.DiscourageGoto` - replaced by the same sniff which is now available upstream: `Generic.PHP.DiscourageGoto`. + - `WordPress.WhiteSpace.SemicolonSpacing` - superseded by a bug fix in the upstream `Squiz.WhiteSpace.SemicolonSpacing` sniff. + - `WordPress.WhiteSpace.ArbitraryParenthesesSpacing` - replaced by the same sniff which is now available upstream: `Generic.WhiteSpace.ArbitraryParenthesesSpacing`. +- The following "base" sniffs which were previously already deprecated and turned into abstract base classes, have been removed: + - `WordPress.Arrays.ArrayAssignmentRestrictions` - use the `AbstractArrayAssignmentRestrictionsSniff` class instead. + - `WordPress.Functions.FunctionRestrictions` - use the `AbstractFunctionRestrictionsSniff` class instead. + - `WordPress.Variables.VariableRestrictions` without replacement. +- The following sniffs which were previously deprecated, have been removed: + - `WordPress.Arrays.ArrayDeclaration` - use the other sniffs in the `WordPress.Arrays` category instead. + - `WordPress.CSRF.NonceVerification` - use `WordPress.Security.NonceVerification` instead. + - `WordPress.Functions.DontExtract` - use `WordPress.PHP.DontExtract` instead. + - `WordPress.Variables.GlobalVariables` - use `WordPress.WP.GlobalVariablesOverride` instead. + - `WordPress.VIP.CronInterval` - use `WordPress.WP.CronInterval` instead. + - `WordPress.VIP.DirectDatabaseQuery` - use `WordPress.DB.DirectDatabaseQuery` instead. + - `WordPress.VIP.PluginMenuSlug` - use `WordPress.Security.PluginMenuSlug` instead. + - `WordPress.VIP.SlowDBQuery` - use `WordPress.DB.SlowDBQuery` instead. + - `WordPress.VIP.TimezoneChange` - use `WordPress.WP.TimezoneChange` instead. + - `WordPress.VIP.ValidatedSanitizedInput` - use `WordPress.Security.ValidatedSanitizedInput` instead. + - `WordPress.WP.PreparedSQL` - use `WordPress.DB.PreparedSQL` instead. + - `WordPress.XSS.EscapeOutput` - use `WordPress.Security.EscapeOutput` instead. + - `WordPress.PHP.DiscouragedFunctions` without direct replacement. + The checks previously contained in this sniff were moved to separate sniffs in WPCS 0.11.0. + - `WordPress.Variables.VariableRestrictions` without replacement. + - `WordPress.VIP.AdminBarRemoval` without replacement. + - `WordPress.VIP.FileSystemWritesDisallow` without replacement. + - `WordPress.VIP.OrderByRand` without replacement. + - `WordPress.VIP.PostsPerPage` without replacement. + Part of the previous functionality was split off in WPCS 1.0.0 to the `WordPress.WP.PostsPerPage` sniff. + - `WordPress.VIP.RestrictedFunctions` without replacement. + - `WordPress.VIP.RestrictedVariables` without replacement. + - `WordPress.VIP.SessionFunctionsUsage` without replacement. + - `WordPress.VIP.SessionVariableUsage` without replacement. + - `WordPress.VIP.SuperGlobalInputUsage` without replacement. +- The `WordPress.DB.SlowDBQuery.DeprecatedWhitelistFlagFound` error code which is superseded by the blanket deprecation warning for using the now deprecated WPCS native whitelist comments. +- The `WordPress.PHP.TypeCasts.NonLowercaseFound` error code which has been replaced by the upstream `Generic.PHP.LowerCaseType` sniff. +- The `WordPress.PHP.TypeCasts.LongBoolFound` and `WordPress.PHP.TypeCasts.LongIntFound` error codes which has been replaced by the new upstream `PSR12.Keywords.ShortFormTypeKeywords` sniff. +- The `WordPress.Security.EscapeOutput.OutputNotEscapedShortEcho` error code which was only ever used if WPCS was run on PHP 5.3 with the `short_open_tag` ini directive set to `off`. +- The following sniff categories which were previously deprecated, have been removed, though select categories may be reinstated in the future: + - `CSRF` + - `Functions` + - `Variables` + - `VIP` + - `XSS` +- `WordPress.NamingConventions.ValidVariableName`: The `customVariableWhitelist` property, which had been deprecated since WordPressCS 0.11.0. Use the `customPropertiesWhitelist` property instead. +- `WordPress.Security.EscapeOutput`: The `customSanitizingFunctions` property, which had been deprecated since WordPressCS 0.5.0. Use the `customEscapingFunctions` property instead. +- `WordPress.Security.NonceVerification`: The `errorForSuperGlobals` and `warnForSuperGlobals` properties, which had been deprecated since WordPressCS 0.12.0. +- The `vip_powered_wpcom` function from the `Sniff::$autoEscapedFunctions` list which is used by the `WordPress.Security.EscapeOutput` sniff. +- The `AbstractVariableRestrictionsSniff` class, which was deprecated since WordPressCS 1.0.0. +- The `Sniff::has_html_open_tag()` utility method, which was deprecated since WordPressCS 1.0.0. +- The internal `$php_reserved_vars` property from the `WordPress.NamingConventions.ValidVariableName` sniff in favour of using a PHPCS native property which is now available. +- The class aliases and WPCS native autoloader used for PHPCS cross-version support. +- The unit test framework workarounds for PHPCS cross-version unit testing. +- Support for the `@codingStandardsChangeSetting` annotation, which is generally only used in unit tests. +- The old generic GitHub issue template which was replaced by more specific issue templates in WPCS 1.2.0. + +### Fixed +- Support for PHP 7.3. + `PHP_CodeSniffer` < 3.3.1 was not fully compatible with PHP 7.3. Now the minimum required PHPCS has been upped to `PHP_CodeSniffer` 3.3.1, WordPressCS will run on PHP 7.3 without issue. +- `WordPress.Arrays.ArrayDeclarationSpacing`: improved fixing of the placement of array items following an array item with a trailing multi-line comment. +- `WordPress.NamingConventions.ValidFunctionName`: the sniff will no longer throw false positives nor duplicate errors for methods declared in nested anonymous classes. + The error message has also been improved for methods in anonymous classes. +- `WordPress.NamingConventions.ValidFunctionName`: the sniff will no longer throw false positives for PHP 4-style class constructors/destructors where the name of the constructor/destructor method did not use the same case as the class name. + + +## [1.2.1] - 2018-12-18 + +Note: This will be the last release supporting PHP_CodeSniffer 2.x. + +### Changed +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.7`. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff will now report the error for hook names and constant names declared with `define()` on the line containing the parameter for the hook/constant name. Previously, it would report the error on the line containing the function call. +- Various minor housekeeping fixes to inline documentation, rulesets, code. + +### Removed +- `comment_author_email_link()`, `comment_author_email()`, `comment_author_IP()`, `comment_author_link()`, `comment_author_rss()`, `comment_author_url_link()`, `comment_author_url()`, `comment_author()`, `comment_date()`, `comment_excerpt()`, `comment_form_title()`, `comment_form()`, `comment_id_fields()`, `comment_ID()`, `comment_reply_link()`, `comment_text_rss()`, `comment_text()`, `comment_time()`, `comment_type()`, `comments_link()`, `comments_number()`, `comments_popup_link()`, `comments_popup_script()`, `comments_rss_link()`, `delete_get_calendar_cache()`, `edit_bookmark_link()`, `edit_comment_link()`, `edit_post_link()`, `edit_tag_link()`, `get_footer()`, `get_header()`, `get_sidebar()`, `get_the_title()`, `next_comments_link()`, `next_image_link()`, `next_post_link()`, `next_posts_link()`, `permalink_anchor()`, `posts_nav_link()`, `previous_comments_link()`, `previous_image_link()`, `previous_post_link()`, `previous_posts_link()`, `sticky_class()`, `the_attachment_link()`, `the_author_link()`, `the_author_meta()`, `the_author_posts_link()`, `the_author_posts()`, `the_category_rss()`, `the_category()`, `the_content_rss()`, `the_content()`, `the_date_xml()`, `the_excerpt_rss()`, `the_excerpt()`, `the_feed_link()`, `the_ID()`, `the_meta()`, `the_modified_author()`, `the_modified_date()`, `the_modified_time()`, `the_permalink()`, `the_post_thumbnail()`, `the_search_query()`, `the_shortlink()`, `the_tags()`, `the_taxonomies()`, `the_terms()`, `the_time()`, `the_title_rss()`, `the_title()`, `wp_enqueue_script()`, `wp_meta()`, `wp_shortlink_header()` and `wp_shortlink_wp_head()` from the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. This affects the `WordPress.Security.EscapeOutput` sniff. + +### Fixed +- The `WordPress.WhiteSpace.PrecisionAlignment` sniff would loose the value of a custom set `ignoreAlignmentTokens` property when scanning more than one file. + + +## [1.2.0] - 2018-11-12 + +### Added +- New `WordPress.PHP.TypeCasts` sniff to the `WordPress-Core` ruleset. + This new sniff checks that PHP type casts are: + * lowercase; + * short form, i.e. `(bool)` not `(boolean)`; + * normalized, i.e. `(float)` not `(real)`. + Additionally, the new sniff discourages the use of the `(unset)` and `(binary)` type casts. +- New `WordPress.Utils.I18nTextDomainFixer` sniff which can compehensively replace/add `text-domain`s in a plugin or theme. + Important notes: + - This sniff is disabled by default and intended as a utility tool. + - The sniff will fix the text domains in all I18n function calls as well as in a plugin/theme `Text Domain:` header. + - Passing the following properties will activate the sniff: + - `old_text_domain`: an array with one or more (old) text domains which need to be replaced; + - `new_text_domain`: the correct (new) text domain as a string. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff will now also verify that namespace names use a valid prefix. + * The sniff allows for underscores and (other) non-word characters in a passed prefix to be converted to namespace separators when used in a namespace name. + In other words, if a prefix of `my_plugin` is passed as a value to the `prefixes` property, a namespace name of both `My\Plugin` as well as `My_Plugin\\`, will be accepted automatically. + * Passing a prefix property value containing namespace separators will now also be allowed and will no longer trigger a warning. +- `WordPress` to the prefix blacklist for the `WordPress.NamingConventions.PrefixAllGlobals` sniff. + While the prefix cannot be `WordPress`, a prefix can still _start with_ or _contain_ `WordPress`. +- Additional unit tests covering a change in the tokenizer which will be included in the upcoming `PHP_CodeSniffer` 3.4.0 release. +- A variety of issue templates for use on GitHub. + +### Changed +- The `Sniff::valid_direct_scope()` method will now return the `$stackPtr` to the valid scope if a valid direct scope has been detected. Previously, it would return `true`. +- Minor hardening and efficiency improvements to the `WordPress.NamingConventions.PrefixAllGlobals` sniff. +- The inline documentation of the `WordPress-Core` ruleset has been updated to be in line again with [the handbook](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/). +- The inline links to documentation about the VIP requirements have been updated. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) to recommend using `PHPCompatibilityWP` rather than `PHPCompatibility`. +- All sniffs are now also being tested against PHP 7.3 for consistent sniff results. + Note: PHP 7.3 is only supported in combination with PHPCS 3.3.1 or higher as `PHP_CodeSniffer` itself has an incompatibility in earlier versions. +- Minor grammar fixes in text strings and documentation. +- Minor consistency improvement for the unit test case files. +- Minor tweaks to the `composer.json` file. +- Updated the PHPCompatibility `dev` dependency. + +### Removed +- The `WordPress.WhiteSpace.CastStructureSpacing.NoSpaceAfterCloseParenthesis` error code as an error for the same issue was already being thrown by an included upstream sniff. + +### Fixed +- The `WordPress.CodeAnalysis.EmptyStatement` would throw a false positive for an empty condition in a `for()` statement. +- The `Sniff::is_class_property()` method could, in certain circumstances, incorrectly recognize parameters in a method declaration as class properties. It would also, incorrectly, fail to recognize class properties when the object they are declared in, was nested in parentheses. + This affected, amongst others, the `GlobalVariablesOverride` sniff. +- The `Sniff::get_declared_namespace_name()` method could get confused over whitespace and comments within a namespace name, which could lead to incorrect results (mostly underreporting). + This affected, amongst others, the `GlobalVariablesOverride` sniff. + The return value of the method will now no longer contain any whitespace or comments encountered. +- The `Sniff::has_whitelist_comment()` method would sometimes incorrectly regard `// phpcs:set` comments as whitelist comments. + +## [1.1.0] - 2018-09-10 + +### Added +- New `WordPress.PHP.NoSilencedErrors` sniff. This sniff replaces the `Generic.PHP.NoSilencedErrors` sniff which was previously used and included in the `WordPress-Core` ruleset. + The WordPress specific version of the sniff differs from the PHPCS version in that it: + * Allows the error control operator `@` if it preceeds a function call to a limited list of PHP functions for which no amount of error checking can prevent a PHP warning from being thrown. + * Allows for a used-defined list of (additional) function names to be passed to the sniff via the `custom_whitelist` property in a custom ruleset, for which - if the error control operator is detected in front of a function call to one of the functions in this whitelist - no warnings will be thrown. + * Displays a brief snippet of code in the `warning` message text to show the context in which the error control operator is being used. The length of the snippet (in tokens) can be customized via the `context_length` property. + * Contains a public `use_default_whitelist` property which can be set from a custom ruleset which regulates whether or not the standard whitelist of PHP functions should be used by the sniff. + The user-defined whitelist will always be respected. + By default, this property is set to `true` for the `WordPress-Core` ruleset and to `false` for the `WordPress-Extra` ruleset (which is stricter regarding these kind of best practices). +- Metrics to the `WordPress.NamingConventions.PrefixAllGlobals` sniff to aid people in determining the most commonly used prefix in a legacy project. + For an example of how to use this feature, please see the detailed explanation in the [pull request](https://github.com/WordPress/WordPress-Coding-Standards/pull/1437). + +### Changed +- The `PEAR.Functions.FunctionCallSignature` sniff, which is part of the `WordPress-Core` ruleset, used to allow multiple function call parameters per line in multi-line function calls. This will no longer be allowed. + As of this release, if a function call is multi-line, each parameter should start on a new line and an `error` will be thrown if the code being analysed does not comply with that rule. + The sniff behaviour for single-line function calls is not affected by this change. +- Moved the `WordPress.CodeAnalysis.EmptyStatement` sniff from the `WordPress-Extra` to the `WordPress-Core` ruleset. +- Moved the `Squiz.PHP.CommentedOutCode` sniff from the `WordPress-Docs` to the `WordPress-Extra` ruleset and lowered the threshold for determining whether or not a comment is commented out code from 45% to 40%. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff now has improved support for recognizing whether or not (non-prefixed) globals are declared in the context of unit tests. +- The `is_foreach_as()` method has been moved from the `GlobalVariablesOverrideSniff` class to the WordPress `Sniff` base class. +- The `Sniff::is_token_in_test_method()` utility method now has improved support for recognizing test methods in anonymous classes. +- Minor efficiency improvement to the `Sniff::is_safe_casted()` method. +- CI: Minor tweaks to the Travis script. +- CI: Improved Composer scripts for use by WPCS developers. +- Dev: Removed IDE specific files from `.gitignore`. +- Readme: Improved the documentation about the project history and the badge display. + +### Fixed +- The `WordPress.Security.ValidatedSanitizedInput` sniff will now recognize array keys in superglobals independently of the string quote-style used for the array key. +- The `WordPress.WhiteSpace.PrecisionAlignment` sniff will no longer throw false positives for DocBlocks for JavaScript functions within inline HTML. +- `WordPress.WP.DeprecatedClasses`: The error codes for this sniff were unstable as they were based on the code being analysed instead of on fixed values. +- Various bugfixes for the `WordPress.WP.GlobalVariablesOverride` sniff: + - Previously, the sniff only checked variables in the global namespace when a `global` statement would be encountered. As of now, all variable assignments in the global namespace will be checked. + - Nested functions/closures/classes which don't import the global variable will now be skipped over when encountered within another function, preventing false positives. + - Parameters in function declarations will no longer throw false positives. + - The error message for assignments to a subkey of the `$GLOBALS` superglobal has been improved. + - Various efficiency improvements. +- The `Sniff::is_in_isset_or_empty()` method presumed the WordPress coding style regarding code layout, which could lead to incorrect results (mostly underreporting). + This affected, amongst others, the `WordPress.Security.ValidatedSanitizedInput` sniff. +- Broken links in the inline developer documentation. + + +## [1.0.0] - 2018-07-25 + +### Important information about this release: + +If you use the WordPress Coding Standards with a custom ruleset, please be aware that a number of sniffs have been moved between categories and that the old sniff names have been deprecated. +If you selectively include any of these sniffs in your custom ruleset or set custom property values for these sniffs, your custom ruleset will need to be updated. + +The `WordPress-VIP` ruleset has also been deprecated. If you used that ruleset to check your theme/plugin for hosting on the WordPress.com VIP platform, please use the [Automattic VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) instead. +If you used that ruleset for any other reason, you should probably use the `WordPress-Extra` or `WordPress` ruleset instead. + +These and some related changes have been annotated in detail in the `Deprecated` section of this changelog. + +Please read the complete changelog carefully before you upgrade. + +If you are a maintainer of an external standard based on WPCS and any of your custom sniffs are based on or extend WPCS sniffs, the same applies. + +### Added +- `WordPress.PHP.PregQuoteDelimiter` sniff to the `WordPress-Extra` ruleset to warn about calls to `preg_quote()` which don't pass the `$delimiter` parameter. +- `WordPress.Security.SafeRedirect` sniff to the `WordPress-Extra` ruleset to warn about potential open redirect vulnerabilities. +- `WordPress.WP.DeprecatedParameterValues` sniff to the `WordPress-Extra` ruleset to detect deprecated parameter values being passed to select functions. +- `WordPress.WP.EnqueuedResourceParameters` sniff to the `WordPress-Extra` ruleset to detect: + - Calls to the script/style register/enqueue functions which don't pass a `$version` for the script/style, which can cause issues with browser caching; and/or + - Calls to the register/enqueue script functions which don't pass the `$in_footer` parameter, which causes scripts - by default - to be loaded in the HTML header in a layout rendering blocking manner. +- Detection of calls to `strip_tags()` and various PHP native `..rand()` functions to the `WordPress.WP.AlternativeFunctions` sniff. +- `readonly()` to the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. This affects the `WordPress.Security.EscapeOutput` sniff. +- The `WordPress.Security.PluginMenuSlug`, `WordPress.WP.CronInterval`, `WordPress.WP.PostsPerPage` and `WordPress.WP.TimezoneChange` sniffs are now included in the `WordPress-Extra` ruleset. Previously, they were already included in the `WordPress` and `WordPress-VIP` rulesets. +- New utility method `Sniff::is_use_of_global_constant()`. +- A rationale to the package suggestion made via `composer.json`. +- CI: Validation of the `composer.json` file on each build. +- A wiki page with instructions on how to [set up WPCS to run with Eclipse on XAMPP](https://github.com/WordPress/WordPress-Coding-Standards/wiki/How-to-use-WPCS-with-Eclipse-and-XAMPP). +- Readme: A link to an external resource with more examples for setting up PHPCS for CI. +- Readme: A badge-based quick overview of the project. + +### Changed +- The `WordPress` ruleset no longer includes the `WordPress-VIP` ruleset, nor does it include any of the (deprecated) `VIP` sniffs anymore. +- The following sniffs have been moved to a new category: + - `CronInterval` from the `VIP` category to the `WP` category. + - `DirectDatabaseQuery` from the `VIP` category to the `DB` category. + - `DontExtract` from the `Functions` category to the `PHP` category. + - `EscapeOutput` from the `XSS` category to the `Security` category. + - `GlobalVariables` from the `Variables` category to the `WP` category. + - `NonceVerification` from the `CSRF` category to the `Security` category. + - `PluginMenuSlug` from the `VIP` category to the `Security` category. + - `PreparedSQL` from the `WP` category to the `DB` category. + - `SlowDBQuery` from the `VIP` category to the `DB` category. + - `TimezoneChange` from the `VIP` category to the `WP` category. + - `ValidatedSanitizedInput` from the `VIP` category to the `Security` category. +- The `WordPress.VIP.PostsPerPage` sniff has been split into two distinct sniffs: + - `WordPress.WP.PostsPerPage` which will check for the use of a high pagination limit and will throw a `warning` when this is encountered. For the `VIP` ruleset, the error level remains `error`. + - `WordPress.VIP.PostsPerPage` wich will check for disabling of pagination. +- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `4.6`. +- The `WordPress.WP.AlternativeFunctions` sniff will now only throw a warning if/when the recommended alternative function is available in the minimum supported WP version of a project. + In addition to this, certain alternatives are only valid alternatives in certain circumstances, like when the WP version only supports the first parameter of the PHP function it is trying to replace. + This will now be taken into account for: + - `wp_strip_all_tags()` is only a valid alternative for the PHP native `strip_tags()` when the second parameter `$allowed_tags` has not been passed. + - `wp_parse_url()` only added support for the second parameter `$component` of the PHP native `parse_url()` function in WP 4.7.0. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 4.9. +- The `WordPress.WP.GlobalVariablesOverride` sniff will now display the name of the variable being overridden in the error message. +- The `WordPress.WP.I18n` sniff now extends the `AbstractFunctionRestrictionSniff`. +- Assignments in conditions in ternaries as detected by the `WordPress.CodeAnalysis.AssignmentInCondition` sniff will now be reported under a separate error code `FoundInTernaryCondition`. +- The default error level for the notices from the `WordPress.DB.DirectDatabaseQuery` sniff has been lowered from `error` to `warning`. For the `VIP` ruleset, the error level remains `error`. +- The default error level for the notices from the `WordPress.Security.PluginMenuSlug` sniff has been lowered from `error` to `warning`. For the `VIP` ruleset, the error level remains `error`. +- The default error level for the notices from the `WordPress.WP.CronInterval` sniff has been lowered from `error` to `warning`. For the `VIP` ruleset, the error level remains `error`. +- The `Sniff::get_function_call_parameters()` utility method now has improved handling of closures when passed as function call parameters. +- Rulesets: a number of error codes were previously silenced by explicitly `exclude`-ing them. Now, they will be silenced by setting the `severity` to `0` which makes it more easily discoverable for maintainers of custom rulesets how to enable these error codes again. +- Various performance optimizations which should most notably make a difference when running WPCS on PHP 7. +- References to the WordPress.com VIP platform have been clarified. +- Unit Tests: custom properties set in unit test files are reset after use. +- Various improvements to the ruleset used by the WPCS project itself and minor code clean up related to this. +- CI: Each change will now also be tested against the lowest supported PHPCS 3 version. +- CI: Each change will now also be checked for PHP cross-version compatibility. +- CI: The rulesets will now also be tested on each change to ensure no unexpected messages are thrown. +- CI: Minor changes to the script to make the build testing faster. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) for the changes contained in this release and to reflect current best practices regarding the PHPCompatibility standard. +- The instructions on how to set up WPCS for various IDEs have been moved from the `README` to the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki). +- Updated output examples in `README.md` and `CONTRIBUTING.md` and other minor changes to these files. +- Updated references to the PHPCompatibility standard to reflect its new location and recommend using PHPCompatibilityWP. + +### Deprecated +- The `WordPress-VIP` ruleset has been deprecated. + For checking a theme/plugin for hosting on the WordPress.com VIP platform, please use the [Automattic VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) instead. + If you used the `WordPress-VIP` ruleset for any other reason, you should probably use the `WordPress-Extra` or `WordPress` ruleset instead. +- The following sniffs have been deprecated and will be removed in WPCS 2.0.0: + - `WordPress.CSRF.NonceVerification` - use `WordPress.Security.NonceVerification` instead. + - `WordPress.Functions.DontExtract` - use `WordPress.PHP.DontExtract` instead. + - `WordPress.Variables.GlobalVariables` - use `WordPress.WP.GlobalVariablesOverride` instead. + - `WordPress.VIP.CronInterval` - use `WordPress.WP.CronInterval` instead. + - `WordPress.VIP.DirectDatabaseQuery` - use `WordPress.DB.DirectDatabaseQuery` instead. + - `WordPress.VIP.PluginMenuSlug` - use `WordPress.Security.PluginMenuSlug` instead. + - `WordPress.VIP.SlowDBQuery` - use `WordPress.DB.SlowDBQuery` instead. + - `WordPress.VIP.TimezoneChange` - use `WordPress.WP.TimezoneChange` instead. + - `WordPress.VIP.ValidatedSanitizedInput` - use `WordPress.Security.ValidatedSanitizedInput` instead. + - `WordPress.WP.PreparedSQL` - use `WordPress.DB.PreparedSQL` instead. + - `WordPress.XSS.EscapeOutput` - use `WordPress.Security.EscapeOutput` instead. + - `WordPress.VIP.AdminBarRemoval` without replacement. + - `WordPress.VIP.FileSystemWritesDisallow` without replacement. + - `WordPress.VIP.OrderByRand` without replacement. + - `WordPress.VIP.RestrictedFunctions` without replacement. + - `WordPress.VIP.RestrictedVariables` without replacement. + - `WordPress.VIP.SessionFunctionsUsage` without replacement. + - `WordPress.VIP.SessionVariableUsage` without replacement. + - `WordPress.VIP.SuperGlobalInputUsage` without replacement. +- The following sniff categories have been deprecated and will be removed in WPCS 2.0.0: + - `CSRF` + - `Variables` + - `XSS` +- The `posts_per_page` property in the `WordPress.VIP.PostsPerPage` sniff has been deprecated as the related functionality has been moved to the `WordPress.WP.PostsPerPage` sniff. + See [WP PostsPerPage: post limit](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#wp-postsperpage-post-limit) for more information about this property. +- The `exclude` property which is available to most sniffs which extend the `AbstractArrayAssignmentRestrictions`, `AbstractFunctionRestrictions` and `AbstractVariableRestrictions` classes or any of their children, used to be a `string` property and expected a comma-delimited list of groups to exclude. + The type of the property has now been changed to `array`. Custom rulesets which pass this property need to be adjusted to reflect this change. + Support for passing the property as a comma-delimited string has been deprecated and will be removed in WPCS 2.0.0. + See [Excluding a group of checks](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#excluding-a-group-of-checks) for more information about the sniffs affected by this change. +- The `AbstractVariableRestrictionsSniff` class has been deprecated as all sniffs depending on this class have been deprecated. Unless a new sniff is created in the near future which uses this class, the abstract class will be removed in WPCS 2.0.0. +- The `Sniff::has_html_open_tag()` utility method has been deprecated as it is now only used by deprecated sniffs. The method will be removed in WPCS 2.0.0. + +### Removed +- `cancel_comment_reply_link()`, `get_bookmark()`, `get_comment_date()`, `get_comment_time()`, `get_template_part()`, `has_post_thumbnail()`, `is_attachement()`, `post_password_required()` and `wp_attachment_is_image()` from the list of auto-escaped functions `Sniff::$autoEscapedFunctions`. This affects the `WordPress.Security.EscapeOutput` sniff. +- WPCS no longer explicitly supports HHVM and builds are no longer tested against HHVM. + For now, running WPCS on HHVM to test PHP code may still work for a little while, but HHVM has announced they are [dropping PHP support](https://hhvm.com/blog/2017/09/18/the-future-of-hhvm.html). + +### Fixed +- Compatibility with PHP 7.3. A change in PHP 7.3 was causing the `WordPress.DB.RestrictedClasses`, `WordPress.DB.RestrictedFunctions` and the `WordPress.WP.AlternativeFunctions` sniffs to fail to correctly detect issues. +- Compatibility with the latest releases from [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer). + PHPCS 3.2.0 introduced new annotations which can be used inline to selectively disable/ignore certain sniffs. + **Note**: The initial implementation of the new annotations was buggy. If you intend to start using these new style annotations, you are strongly advised to use PHPCS 3.3.0 or higher. + For more information about these annotations, please refer to the [PHPCS Wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#ignoring-parts-of-a-file). + - The [WPCS native whitelist comments](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors) can now be combined with the new style PHPCS whitelist annotations in the `-- for reasons` part of the annotation. + - `WordPress.Arrays.ArrayDeclarationSpacing`: the fixer will now handle the new style annotations correctly. + - `WordPress.Arrays.CommaAfterArrayItem`: prevent a fixer loop when new style annotations are encountered. + - `WordPress.Files.FileName`: respect the new style annotations if these would selectively disable this sniff. + - `WordPress.WhiteSpace.ControlStructureSpacing`: handle the new style annotations correctly for the "blank line at the start/end of control structure" checks and prevent a fixer conflict when the new style annotations are encountered. + - `WordPress.WhiteSpace.PrecisionAlignment`: allow for checking of for precision alignment on lines containing new style annotations when `phpcs` is run with `--ignore-annotations`. +- The `Sniff::is_test_class()` method now has improved recognition of namespaced test classes. + This positively affects the `WordPress.Files.FileName`, `WordPress.NamingConventions.PrefixAllGlobals` and `WordPress.WP.GlobalVariablesOverride` sniffs, which each allow for test classes to (partially) not comply with the rules these sniffs check for. + This fixes the following bugs: + - Namespaced classes where the classname was one of the whitelisted global classes would incorrectly be recognized as a test class, even though they were not the same class. + This also happened if a namespaced class `extend`ed one of the whitelisted global classes. + - A namespaced custom test class where the name was split between the namespace declaration and the extended class declaration was not correctly recognized as the whitelisted test class. + - A namespaced test class which extended another class using a FQCN prefixed with a `\\` would not be correctly recognized. + - The `custom_test_class_whitelist` property which is available for each of these sniffs expects to be passed a Fully Qualified Class Name. FQCNs prefixed with a global namespace indicator will now be correctly handled. +- The determination of whether a `T_STRING` is a function call or not has been improved in the `AbstractFunctionRestrictions` class. This improvement benefits all sniffs which extend this abstract and any of its children (> 10 sniffs) and fixes the following false positives: + - Class declarations will no longer be confused with function calls. + - Use statement alias declarations will no longer be confused with function calls. +- Various bugs in the `WordPress.Arrays.ArrayIndentation` sniff: + - The sniff will no longer throw false positives or try to fix multi-line text strings where the closing quote is on a line by itself. + - The sniff would go into a fixer loop when it encountered a multi-line trailing comment after an array item. +- The `WordPress.CodeAnalysis.AssignmentInCondition` was throwing false positives for ternaries in nested, but unrelated, parentheses. +- The `WordPress.CodeAnalysis.EmptyStatement` and `WordPress.Files.FileName` sniffs underreported as they did not take PHP short open echo tags into account. +- Various bugs in the `WordPress.NamingConventions.PrefixAllGlobals` sniff: + - Parameters in a closure declaration were incorrectly being regarded as global variables. + - Non-prefixed variables created by a `foreach()` construct in the global namespace were previously not detected. + - Non-prefixed globals found in namespaced test classes should be ignored by the sniff, but were not. + - Definition of non-prefixed global WP constants which are intended to be overruled, should not trigger an error from this sniff. + - The sniff presumed the WP naming conventions for PHP constructs, while it should check for the construct being prefixed regardless of whether camelCase, PascalCase, snake_case or other naming conventions are used. + - The sniff presumed the WP naming conventions for prefixes used in hook names. The sniff will now be more tolerant when non-conventional word separators are used in prefixes for hooks. +- The `WordPress.NamingConventions.ValidFunctionName` sniff no longer "hides" one message behind another. The sniff will now correctly throw a message about function names not being in `snake_case`, even when the `FunctionDoubleUnderscore` or `MethodDoubleUnderscore` error codes have been excluded. +- The `WordPress.PHP.StrictInArray` sniff will no longer throw an error when `in_array`, `array_search` or `array_keys` are used in a file `use` statement. +- Various bugs in the `WordPress.Security.EscapeOutput` sniff: + - A limited list of native PHP constants which are safe to use, such as `PHP_EOL`, has been added. When any of these constants are encountered, the sniff will no longer demand output escaping for them. + - The sniff was underreporting issues with variables passed to `trigger_error()`. + - While reporting an issue, sometimes the wrong error message was used. The sniff logic has been adjusted to prevent this. + - The sniff will now correctly ignore the open and close brackets of short arrays. + - The sniff would throw false positives when `echo`, `print`, `exit` or `die` were encountered as constants, function or class names. While it may not be a good idea to use PHP keywords in such a way, it is allowed, so the sniff should handle this correctly. +- The `WordPress.WhiteSpace.ControlStructureSpacing` sniff would inadvertently throw an error for the spacing around the colon for a return type in a function declaration. +- The `WordPress.WP.AlternativeFunctions` sniff used to flag all function calls to `file_get_contents()` twice, suggesting to use `wp_remote_get()` - which is only applicable for remote URLs - and the `WP_FileSystem` API - which is not needed when just _reading_ local files. These messages contradicted each other. + The sniff will now try to determine whether the file requested is local or remote and will only throw a `warning` suggesting to use `wp_remote_get()`, if a remote URL is being requested or when it could not be determined if the requested file is local or remote. +- The expected default value for `wp_upload_bits()` in the `WordPress.WP.DeprecatedParameters` sniff. +- The `WordPress.WP.GlobalVariablesOverride` sniff previously did not detect variables created by a `foreach()` construct which would override WP global variables. +- Various bugs in the `WordPress.WP.I18n` sniff: + - The sniff will no longer throw false positives for calls to methods carrying the same name as any of the global WP functions being targeted and has improved handling of parse errors and live coding. + - A numeric `0` would throw a false positive for "no translatable content found". +- The fixer in the `WordPress.WhiteSpace.ControlStructureSpacing` sniff will no longer inadvertently remove return type declarations. +- Various bugs in the `WordPress.WhiteSpace.PrecisionAlignment` sniff: + - Inline HTML before the first PHP open tag was not being examined. + - Files which only contained short open echo tags for PHP were not being examined. + - The last line of inline HTML in a file was not being examined. +- Some best practice sniffs presumed the WordPress coding style regarding code layout, which could lead to incorrect results (mostly underreporting). + The following sniffs have received fixes related to this: + - `WordPress.DB.PreparedSQL` + - `WordPress.NamingConventions.ValidVariableName` + - `WordPress.WP.CronInterval` + - `WordPress.WP.I18n` +- Various minor fixes based on visual inspection and Scrutinizer analysis feedback. +- Typo in the instructions contained in `CONTRIBUTING.md`. +- Broken link in the `README.md` file. + + +## [0.14.1] - 2018-02-15 + +### Fixed +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff contained a bug which could inadvertently trigger class autoloading of the project being sniffed and by extension could cause fatal errors during the PHPCS run. + +## [0.14.0] - 2017-11-01 + +### Added +- `WordPress.Arrays.MultipleStatementAlignment` sniff to the `WordPress-Core` ruleset which will align the array assignment operator for multi-item, multi-line associative arrays. + This new sniff offers four custom properties to customize its behaviour: [`ignoreNewlines`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-allow-for-new-lines), [`exact`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-allow-non-exact-alignment), [`maxColumn`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-maximum-column) and [`alignMultilineItems`](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#array-alignment-dealing-with-multi-line-items). +- `WordPress.DB.PreparedSQLPlaceholders` sniff to the `WordPress-Core` ruleset which will analyse the placeholders passed to `$wpdb->prepare()` for their validity, check whether queries using `IN ()` and `LIKE` statements are created correctly and will check whether a correct number of replacements are passed. + This sniff should help detect queries which are impacted by the security fixes to `$wpdb->prepare()` which shipped with WP 4.8.2 and 4.8.3. + The sniff also adds a new ["PreparedSQLPlaceholders replacement count" whitelist comment](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors#preparedsql-placeholders-vs-replacements) for pertinent replacement count vs placeholder mismatches. Please consider carefully whether something could be a bug when you are tempted to use the whitelist comment and if so, [report it](https://github.com/WordPress/WordPress-Coding-Standards/issues/new). +- `WordPress.PHP.DiscourageGoto` sniff to the `WordPress-Core` ruleset. +- `WordPress.PHP.RestrictedFunctions` sniff to the `WordPress-Core` ruleset which initially forbids the use of `create_function()`. + This was previous only discouraged under certain circumstances. +- `WordPress.WhiteSpace.ArbitraryParenthesesSpacing` sniff to the `WordPress-Core` ruleset which checks the spacing on the inside of arbitrary parentheses. +- `WordPress.WhiteSpace.PrecisionAlignment` sniff to the `WordPress-Core` ruleset which will throw a warning when precision alignment is detected in PHP, JS and CSS files. +- `WordPress.WhiteSpace.SemicolonSpacing` sniff to the `WordPress-Core` ruleset which will throw a (fixable) error when whitespace is found before a semi-colon, except for when the semi-colon denotes an empty `for()` condition. +- `WordPress.CodeAnalysis.AssignmentInCondition` sniff to the `WordPress-Extra` ruleset. +- `WordPress.WP.DiscouragedConstants` sniff to the `WordPress-Extra` and `WordPress-VIP` rulesets to detect usage of deprecated WordPress constants, such as `STYLESHEETPATH` and `HEADER_IMAGE`. +- Ability to pass the `minimum_supported_version` to use for the `DeprecatedFunctions`, `DeprecatedClasses` and `DeprecatedParameters` sniff in one go. You can pass a `minimum_supported_wp_version` runtime variable for this [from the command line or pass it using a `config` directive in a custom ruleset](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#setting-minimum-supported-wp-version-for-all-sniffs-in-one-go-wpcs-0140). +- `Generic.Formatting.MultipleStatementAlignment` - customized to have a `maxPadding` of `40` -, `Generic.Functions.FunctionCallArgumentSpacing` and `Squiz.WhiteSpace.ObjectOperatorSpacing` to the `WordPress-Core` ruleset. +- `Squiz.Scope.MethodScope`, `Squiz.Scope.MemberVarScope`, `Squiz.WhiteSpace.ScopeKeywordSpacing`, `PSR2.Methods.MethodDeclaration`, `Generic.Files.OneClassPerFile`, `Generic.Files.OneInterfacePerFile`, `Generic.Files.OneTraitPerFile`, `PEAR.Files.IncludingFile`, `Squiz.WhiteSpace.LanguageConstructSpacing`, `PSR2.Namespaces.NamespaceDeclaration` to the `WordPress-Extra` ruleset. +- The `is_class_constant()`, `is_class_property` and `valid_direct_scope()` utility methods to the `WordPress\Sniff` class. + +### Changed +- When passing an array property via a custom ruleset to PHP_CodeSniffer, spaces around the key/value are taken as intentional and parsed as part of the array key/value. In practice, this leads to confusion and WPCS does not expect any values which could be preceded/followed by a space, so for the WordPress Coding Standard native array properties, like `customAutoEscapedFunction`, `text_domain`, `prefixes`, WPCS will now trim whitespace from the keys/values received before use. +- The WPCS native whitelist comments used to only work when they were put on the _end of the line_ of the code they applied to. As of now, they will also be recognized when they are be put at the _end of the statement_ they apply to. +- The `WordPress.Arrays.ArrayDeclarationSpacing` sniff used to enforce all associative arrays to be multi-line. The handbook has been updated to only require this for multi-item associative arrays and the sniff has been updated accordingly. + [The original behaviour can still be enforced](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#arrays-forcing-single-item-associative-arrays-to-be-multi-line) by setting the new `allow_single_item_single_line_associative_arrays` property to `false` in a custom ruleset. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff will now allow for a limited list of WP core hooks which are intended to be called by plugins and themes. +- The `WordPress.PHP.DiscouragedFunctions` sniff used to include `create_function`. This check has been moved to the new `WordPress.PHP.RestrictedFunctions` sniff. +- The `WordPress.PHP.StrictInArray` sniff now has a separate error code `FoundNonStrictFalse` for when the `$strict` parameter has been set to `false`. This allows for excluding the warnings for that particular situation, which will normally be intentional, via a custom ruleset. +- The `WordPress.VIP.CronInterval` sniff now allows for customizing the minimum allowed cron interval by [setting a property in a custom ruleset](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#vip-croninterval-minimum-interval). +- The `WordPress.VIP.RestrictedFunctions` sniff used to prohibit the use of certain WP native functions, recommending the use of `wpcom_vip_get_term_link()`, `wpcom_vip_get_term_by()` and `wpcom_vip_get_category_by_slug()` instead, as the WP native functions were not being cached. As the results of the relevant WP native functions are cached as of WP 4.8, the advice has now been reversed i.e. use the WP native functions instead of `wpcom...` functions. +- The `WordPress.VIP.PostsPerPage` sniff now allows for customizing the `post_per_page` limit for which the sniff will trigger by [setting a property in a custom ruleset](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#vip-postsperpage-post-limit). +- The `WordPress.WP.I18n` sniff will now allow and actively encourage omitting the text domain in I18n function calls if the text domain passed via the `text_domain` property is `default`, i.e. the domain used by Core. + When `default` is one of several text domains passed via the `text_domain` property, the error thrown when the domain is missing has been downgraded to a `warning`. +- The `WordPress.XSS.EscapeOutput` sniff now has a separate error code `OutputNotEscapedShortEcho` and the error message texts have been updated. +- Moved `Squiz.PHP.Eval` from the `WordPress-Extra` and `WordPress-VIP` to the `WordPress-Core` ruleset. +- Removed two sniffs from the `WordPress-VIP` ruleset which were already included via the `WordPress-Core` ruleset. +- The unit test suite is now compatible with PHPCS 3.1.0+ and PHPUnit 6.x. +- Some tidying up of the unit test case files. +- All sniffs are now also being tested against PHP 7.2 for consistent sniff results. +- An attempt is made to detect potential fixer conflicts early via a special build test. +- Various minor documentation fixes. +- Improved the Atom setup instructions in the Readme. +- Updated the unit testing information in Contributing. +- Updated the [custom ruleset example](https://github.com/WordPress/WordPress-Coding-Standards/blob/develop/phpcs.xml.dist.sample) for the changes contained in this release and to make it more explicit what is recommended versus example code. +- The minimum recommended version for the suggested `DealerDirect/phpcodesniffer-composer-installer` Composer plugin has gone up to `0.4.3`. This patch version fixes support for PHP 5.3. + +### Fixed +- The `WordPress.Arrays.ArrayIndentation` sniff did not correctly handle array items with multi-line strings as a value. +- The `WordPress.Arrays.ArrayIndentation` sniff did not correctly handle array items directly after an array item with a trailing comment. +- The `WordPress.Classes.ClassInstantiation` sniff will now correctly handle detection when using `new $array['key']` or `new $array[0]`. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff did not allow for arbitrary word separators in hook names. +- The `WordPress.NamingConventions.PrefixAllGlobals` sniff did not correctly recognize namespaced constants as prefixed. +- The `WordPress.PHP.StrictInArray` sniff would erronously trigger if the `true` for `$strict` was passed in uppercase. +- The `WordPress.PHP.YodaConditions` sniff could get confused over complex ternaries containing assignments. This has been remedied. +- The `WordPress.WP.PreparedSQL` sniff would erronously throw errors about comments found within a DB function call. +- The `WordPress.WP.PreparedSQL` sniff would erronously throw errors about `(int)`, `(float)` and `(bool)` casts and would also flag the subsequent variable which had been safe casted. +- The `WordPress.XSS.EscapeOutput` sniff would erronously trigger when using a fully qualified function call - including the global namespace `\` indicator - to one of the escaping functions. +- The lists of WP global variables and WP mixed case variables have been synchronized, which fixes some false positives. + + +## [0.13.1] - 2017-08-07 + +### Fixed +- Fatal error when using PHPCS 3.x with the `installed_paths` config variable set via the ruleset. + +## [0.13.0] - 2017-08-03 + +### Added +- Support for PHP_CodeSniffer 3.0.2+. The minimum required PHPCS version (2.9.0) stays the same. +- Support for the PHPCS 3 `--ignore-annotations` command line option. If you pass this option, both PHPCS native `@ignore ...` annotations as well as the WPCS specific [whitelist flags](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors) will be ignored. + +### Changed +- The minimum required PHP version is now 5.3 when used in combination with PHPCS 2.x and PHP 5.4 when used in combination with PHPCS 3.x. +- The way the unit tests can be run is now slightly different for PHPCS 2.x versus 3.x. For more details, please refer to the updated information in the [Contributing Guidelines](CONTRIBUTING.md). +- Release archives will no longer contain the unit tests and other typical development files. You can still get these by using Composer with `--prefer-source` or by checking out a git clone of the repository. +- Various textual improvements to the Readme. +- Various textual improvements to the Contributing Guidelines. +- Minor internal changes. + +### Removed +- The `WordPress.Arrays.ArrayDeclaration` sniff has been deprecated. The last remaining checks this sniff contained have been moved to the `WordPress.Arrays.ArrayDeclarationSpacing` sniff. +- Work-arounds which were in place to support PHP 5.2. + +### Fixed +- A minor bug where the auto-fixer could accidentally remove a comment near an array opener. + + +## [0.12.0] - 2017-07-21 + +### Added +- A default file encoding setting to the `WordPress-Core` ruleset. All files sniffed will now be regarded as `utf-8` by default. +- `WordPress.Arrays.ArrayIndentation` sniff to the `WordPress-Core` ruleset to verify - and auto-fix - the indentation of array items and the array closer for multi-line arrays. This replaces the (partial) indentation fixing contained within the `WordPress.Array.ArrayDeclarationSpacing` sniff. +- `WordPress.Arrays.CommaAfterArrayItem` sniff to the `WordPress-Core` ruleset to enforce that each array item is followed by a comma - except for the last item in a single-line array - and checks the spacing around the comma. This replaces (and improves) the checks which were previously included in the `WordPress.Arrays.ArrayDeclaration` sniff which were causing incorrect fixes and fixer conflicts. +- `WordPress.Functions.FunctionCallSignatureNoParams` sniff to the `WordPress-Core` ruleset to verify that function calls without parameters do not have any whitespace between the parentheses. +- `WordPress.WhiteSpace.DisallowInlineTabs` to the `WordPress-Core` ruleset to verify - and auto-fix - that spaces are used for mid-line alignment. +- `WordPress.WP.CapitalPDangit` sniff to the `WordPress-Core` ruleset to - where relevant - verify that `WordPress` is spelled correctly. For misspellings in text strings and comment text, the sniff can auto-fix violations. +- `Squiz.Classes.SelfMemberReference` whitespace related checks to the `WordPress-Core` ruleset and the additional check for using `self` rather than a FQN to the `WordPress-Extra` ruleset. +- `Squiz.PHP.EmbeddedPhp` sniff to the `WordPress-Core` ruleset to check PHP code embedded within HTML blocks. +- `PSR2.ControlStructures.SwitchDeclaration` to the `WordPress-Core` ruleset to check for the correct layout of `switch` control structures. +- `WordPress.Classes.ClassInstantion` sniff to the `WordPress-Extra` ruleset to detect - and auto-fix - missing parentheses on object instantiation and superfluous whitespace in PHP and JS files. The sniff will also detect `new` being assigned by reference. +- `WordPress.CodeAnalysis.EmptyStatement` sniff to the `WordPress-Extra` ruleset to detect - and auto-fix - superfluous semi-colons and empty PHP open-close tag combinations. +- `WordPress.NamingConventions.PrefixAllGlobals` sniff to the `WordPress-Extra` ruleset to verify that all functions, classes, interfaces, traits, variables, constants and hook names which are declared/defined in the global namespace are prefixed with one of the prefixes provided via a custom property or via the command line. + To activate this sniff, [one or more allowed prefixes should be provided to the sniff](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#naming-conventions-prefix-everything-in-the-global-namespace). This can be done using a custom ruleset or via the command line. + PHP superglobals and WP global variables are exempt from variable name prefixing. Deprecated hook names will also be disregarded when non-prefixed. Back-fills for known native PHP functionality is also accounted for. + For verified exceptions, [unprefixed code can be whitelisted](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors#non-prefixed-functionclassvariableconstant-in-the-global-namespace). + Code in unit test files is automatically exempt from this sniff. +- `WordPress.WP.DeprecatedClasses` sniff to the `WordPress-Extra` ruleset to detect usage of deprecated WordPress classes. +- `WordPress.WP.DeprecatedParameters` sniff to the `WordPress-Extra` ruleset to detect deprecated parameters being passed to WordPress functions with a value other than the expected default. +- The `sanitize_textarea_field()` function to the `sanitizingFunctions` list used by the `WordPress.CSRF.NonceVerification`, `WordPress.VIP.ValidatedSanitizedInput` and `WordPress.XSS.EscapeOutput` sniffs. +- The `find_array_open_closer()` utility method to the `WordPress_Sniff` class. +- Information about setting `installed_paths` using a custom ruleset to the Readme. +- Additional support links to the `composer.json` file. +- Support for Composer PHPCS plugins which sort out the `installed_paths` setting. +- Linting and code-style check of the XML ruleset files provided by WPCS. + +### Changed +- The minimum required PHP_CodeSniffer version to 2.9.0 (was 2.8.1). **Take note**: PHPCS 3.x is not (yet) supported. The next release is expected to fix that. +- Improved support for detecting issues in code using heredoc and/or nowdoc syntax. +- Improved sniff efficiency, precision and performance for a number of sniffs. +- Updated a few sniffs to take advantage of new features and fixes which are included in PHP_CodeSniffer 2.9.0. +- `WordPress.Files.Filename`: The "file name mirrors the class name prefixed with 'class'" check for PHP files containing a class will no longer be applied to typical unit test classes, i.e. for classes which extend `WP_UnitTestCase`, `PHPUnit_Framework_TestCase` and `PHPUnit\Framework\TestCase`. Additional test case base classes can be passed to the sniff using the new [`custom_test_class_whitelist` property](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#custom-unit-test-classes). +- The `WordPress.Files.FileName` sniff allows now for more theme-specific template hierarchy based file name exceptions. +- The whitelist flag for the `WordPress.VIP.SlowQuery` sniff was `tax_query` which was unintuitive. This has now been changed to `slow query` to be in line with other whitelist flags. +- The `WordPress.WhiteSpace.OperatorSpacing` sniff will now ignore operator spacing within `declare()` statements. +- The `WordPress.WhiteSpace.OperatorSpacing` sniff now extends the upstream `Squiz.WhiteSpace.OperatorSpacing` sniff for improved results and will now also examine the spacing around ternary operators and logical (`&&`, `||`) operators. +- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 4.7 and 4.8. Additionally, a number of other deprecated functions which were previously not being detected have been added to the sniff and for a number of functions the "alternative" for the deprecated function has been added/improved. +- The `WordPress.XSS.EscapeOutput` sniff will now also detect unescaped output when the short open echo tags `` PHP open tags. +- `WordPress.Classes.ClassOpeningStatement` sniff to the `WordPress-Core` ruleset to flag - and fix - class opening brace placement. +- `WordPress.NamingConventions.ValidHookName` sniff to the `WordPress-Core` ruleset to flag filter and action hooks which don't comply with the guideline of lowercase letters and underscores. For maintaining backward-compatibility of hook names an `additionalWordDelimiters` property can be added via a custom ruleset. +- `WordPress.Functions.DontExtract` sniff to the `WordPress-Core` ruleset to flag usage of the `extract()` function. +- `WordPress.PHP.POSIXFunctions` sniff to the `WordPress-Core` ruleset to flag usage of regex functions from the POSIX PHP extension which was deprecated since PHP 5.3 and removed in PHP 7. +- `WordPress.DB.RestrictedFunctions` and `WordPress.DB.RestrictedClasses` sniffs to the `WordPress-Core` ruleset to flag usage of direct database calls using PHP functions and classes rather than the WP functions for the same. +- Abstract `AbstractClassRestrictions` parent class to allow for easier sniffing for usage of specific classes. +- `Squiz.Strings.ConcatenationSpacing`, `PSR2.ControlStructures.ElseIfDeclaration`, `PSR2.Files.ClosingTag`, `Generic.NamingConventions.UpperCaseConstantName` to the `WordPress-Core` ruleset. +- Ability to add arbitrary variables to the whitelist via a custom ruleset property for the `WordPress.NamingConventions.ValidVariableName` sniff. +- Ability to use a whitelist comment for tax queries for the `WordPress.VIP.SlowDBQuery` sniff. +- Instructions on how to use WPCS with Atom and SublimeLinter to the Readme. +- Reference to the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki) to the Readme. +- Recommendation to also use the [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) ruleset to the Readme. + +### Changed +- The minimum required PHP_CodeSniffer version to 2.6.0. +- Moved the `WordPress.WP.PreparedSQL` sniff from `WordPress-Extra` to `WordPress-Core`. +- `WordPress.PHP.StrictInArray` will now also flag non-strict usage of `array_keys()` and `array_search()`. +- Added `_deprecated_constructor()` and `_deprecated_hook()` to the list of printing functions. +- Added numerous additional functions to sniff for to the `WordPress.VIP.RestrictedFunctions` sniff as per the VIP guidelines. +- Upped the `posts_per_page` limit from 50 to 100 in `WordPress.VIP.PostsPerPage` sniff as per the VIP guidelines. +- Added `cat_ID` to the whitelisted exceptions for the `WordPress.NamingConventions.ValidVariableName` sniff. +- Added `__debugInfo` to the magic method whitelist for class methods starting with double underscore in the `WordPress.NamingConventions.ValidFunctionName` sniff. +- An error will now also be thrown for non-magic _functions_ using a double underscore prefix - `WordPress.NamingConventions.ValidFunctionName` sniff. +- The `WordPress.Arrays.ArrayAssignmentRestrictions`, `WordPress.Functions.FunctionRestrictions`, `WordPress.Variables.VariableRestrictions` sniffs weren't in actual fact sniffs, but parent classes for child sniffs. These have now all been turned into proper abstract parent classes and moved to the main `WordPress` directory. +- The array provided to `AbstractFunctionRestrictions` can now take a `whitelist` key to whitelist select functions when blocking a group of functions by function prefix. +- Updated installation instructions in the readme. +- The `WordPress-Core` ruleset is now ordered according to the handbook +- The WPCS code base itself now complies with the WordPress-Core, -Extra and -Docs coding standards. +- Various other code quality and code consistency improvements under the hood. + +### Removed +- `Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingBeforeClose` from the `WordPress-Core` standard (was causing duplicate messages for the same issue). +- `Squiz.Commenting.FunctionComment.ScalarTypeHintMissing`, `Squiz.Commenting.InlineComment.NotCapital` from the `WordPress-Docs` standard. +- Removed the sniffing for `get_pages()` from the `WordPress.VIP.RestrictedFunctions` sniff as per the VIP guidelines. +- Removed the sniffing for `extract()` from the `WordPress.VIP.RestrictedFunctions` sniff as it's now covered in a separate sniff. +- Removed the sniffing for the POSIX functions from the `WordPress.PHP.DiscouragedFunctions` sniff as it's now covered in a separate sniff. + +### Fixed +- Error message precision for the `WordPress.NamingConventions.ValidVariableName` sniff. +- Bug in the `WordPress.WhiteSpace.ControlStructureSpacing.BlankLineAfterEnd` sniff which was incorrectly being triggered on last method of class. +- Function name sniffs based on the `AbstractFunctionRestrictions` parent class will now do a case-insensitive function name comparison. +- Function name sniffs in the `WordPress.PHP.DiscouragedFunctions` sniff will now do a case-insensitive function name comparison. +- Whitelist comments directly followed by a PHP closing tag were not being recognized. +- Some PHP Magic constants were not recognized by the `WordPress.XSS.EscapeOutput` sniff. +- An error message suggesting camel caps rather than the intended snake case format in the `WordPress.NamingConventions.ValidFunctionName` sniff. +- `WordPress.WhiteSpace.ControlStructureSpacing` should no longer throw error notices during live code review. +- Errors will be no longer be thrown for methods not complying with the naming conventions when the class extends a parent class or implements an interface - `WordPress.NamingConventions.ValidFunctionName` sniff. + + +## [0.9.0] - 2016-02-01 + +### Added +- `count()` to the list of auto-escaped functions. +- `Squiz.PHP.CommentedOutCode` sniff to `WordPress-VIP` ruleset. +- Support for PHP 5.2. +- `attachment_url_to_postid()` and `parse_url()` to the restricted functions for `WordPress-VIP`. +- `WordPress.VIP.OrderByRand` sniff. +- `WordPress.PHP.StrictInArray` sniff for `WordPress-VIP` and `WordPress-Extra`. +- `get_tag_link()`, `get_category_link()`, `get_cat_ID()`, `url_to_post_id()`, `attachment_url_to_postid()` +`get_posts()`, `wp_get_recent_posts()`, `get_pages()`, `get_children()`, `wp_get_post_terms()` +`wp_get_post_categories()`, `wp_get_post_tags()`, `wp_get_object_terms()`, `term_exists()`, +`count_user_posts()`, `wp_old_slug_redirect()`, `get_adjacent_post()`, `get_previous_post()`, +`get_next_post()` to uncached functions in `WordPress.VIP.RestrictedFunctions` sniff. +- `wp_handle_upload()` and `array_key_exists()` to the list of sanitizing functions. +- Checking for object properties in `WordPress.PHP.YodaConditions` sniff. +- `WordPress.NamingConventions.ValidVariableName` sniff. +- Flagging of function calls incorporated into database queries in `WordPress.WP.PreparedSQL`. +- Recognition of escaping and auto-escaped functions in `WordPress.WP.PreparedSQL`. +- `true`, `false`, and `null` to the tokens ignored in `WordPress.XSS.EscapeOutput`. + +### Fixed +- Incorrect ternary detection in `WordPress.XSS.EscapeOutput` sniff. +- False positives when detecting variables interpolated into strings in the +`WordPress.WP.PreparedSQL` and `WordPress.VIP.ValidatedSanitizedInput` sniffs. +- False positives in `WordPress.PHP.YodaConditions` when the variable is being casted. +- `$wpdb` properties being flagged in `WordPress.WP.PreparedSQL` sniff. +- False positive in `WordPress.PHP.YodaConditions` when the a string is on the left side of the +comparison. + +## [0.8.0] - 2015-10-02 + +### Added +- `implode()` and `join()` to the list of formatting functions in the `WordPress.XSS.EscapeOutput` +sniff. This is useful when you need to have HTML in the `$glue` parameter. +- Support in the `WordPress.XSS.EscapeOutput` sniff for escaping an array of values +using `array_map()`. (Otherwise the support for `implode()` isn't of much use :) +- Docs for running WPCS in Sublime Text. +- `nl2br()` to the list of formatting functions. +- `wp_dropdown_pages()` to the list of printing functions. +- Error codes to all error/warning messages. +- `WordPress.WP.PreparedSQL` sniff for flagging unprepared SQL queries. + +### Removed +- Sniffing for the number of spaces before a closure's opening parenthesis from the +default configuration of the `WordPress.WhiteSpace.ControlStructureSpacing` sniff. It +can be re-enabled per-project as desired. + +### Fixed +- The `WordPress.XSS.EscapeOutput` sniff giving error messages with the closing +parenthesis in them instead of the offending function's name. + +## [0.7.1] - 2015-08-31 + +### Changed +- The default number of spaces before a closure's opening parenthesis from 1 to 0. + +## [0.7.0] - 2015-08-30 + +### Added +- Automatic error fixing to the `WordPress.Arrays.ArrayKeySpacingRestrictions` sniff. +- Functions and closures to the control structures checked by the `WordPress.WhiteSpace.ControlStructureSpacing` +sniff. +- Sniffing and fixing for extra spacing in the `WordPress.WhiteSpace.ControlStructureSpacing` +sniff. (Previously it only checked for insufficient spacing.) +- `.twig` files to the default ignored files. +- `esc_url_raw()` and `hash_equals()` to the list of sanitizing functions. +- `intval()` and `boolval()` to list of unslashing functions. +- `do_shortcode()` to the list of auto-escaped functions. + +### Removed +- `WordPress.Functions.FunctionDeclarationArgumentSpacing` in favor of the upstream +sniff `Squiz.Functions.FunctionDeclarationArgumentSpacing`. + +### Fixed +- Reference to incorrect issue in the inline docs of the `WordPress.VIP.SessionVariableUsage` +sniff. +- `WordPress.XSS.EscapeOutput` sniff incorrectly handling ternary conditions in +`echo` statements without parentheses in some cases. + +## [0.6.0] - 2015-06-30 + +### Added +- Support for `wp_cache_add()` and `wp_cache_delete()`, as well as custom cache +functions,in the `WordPress.VIP.DirectDatabaseQuery` sniff. + +### Removed +- `WordPress.Functions.FunctionRestrictions` and `WordPress.Variables.VariableRestrictions` +from the `WordPress-VIP` standard, since they are just parents for other sniffs. + +## [0.5.0] - 2015-06-01 + +### Added +- `WordPress.CSRF.NonceVerification` sniff to flag form processing without nonce verification. +- `in_array()` and `is_array()` to the list of sanitizing functions. +- Support for automatic error fixing to the `WordPress.Arrays.ArrayDeclaration` sniff. +- `WordPress.PHP.StrictComparisions` to the `WordPress-VIP` and `WordPress-Extra` rulesets. +- `WordPress-Docs` ruleset to sniff for proper commenting. +- `Generic.PHP.LowerCaseKeyword`, `Generic.Files.EndFileNewline`, `Generic.Files.LowercasedFilename`, +`Generic.Formatting.SpaceAfterCast`, and `Generic.Functions.OpeningFunctionBraceKernighanRitchie` to the `WordPress-Core` ruleset. +- `Generic.PHP.DeprecatedFunctions`, `Generic.PHP.ForbiddenFunctions`, `Generic.Functions.CallTimePassByReference`, +`Generic.Formatting.DisallowMultipleStatements`, `Generic.CodeAnalysis.EmptyStatement`, +`Generic.CodeAnalysis.ForLoopShouldBeWhileLoop`, `Generic.CodeAnalysis.ForLoopWithTestFunctionCall`, +`Generic.CodeAnalysis.JumbledIncrementer`, `Generic.CodeAnalysis.UnconditionalIfStatement`, +`Generic.CodeAnalysis.UnnecessaryFinalModifier`, `Generic.CodeAnalysis.UselessOverridingMethod`, +`Generic.Classes.DuplicateClassName`, and `Generic.Strings.UnnecessaryStringConcat` to the `WordPress-Extra` ruleset. +- Error for missing use of `wp_unslash()` on superglobal data to the `WordPress.VIP.ValidatedSanitizedInput` sniff. + +### Changed +- The `WordPress.VIP.ValidatedSanitizedInput` sniff to require sanitization of input even when it is being directly escaped and output. +- The minimum required PHP_CodeSniffer version to 2.2.0. +- The `WordPress.VIP.ValidatedSanitizedInput` and `WordPress.XSS.EscapeOutput` sniffs: +the list of escaping functions was split from the list of sanitizing functions. The `customSanitizingFunctions` +property has been moved to the `ValidatedSanitizedInput` sniff, and the `customEscapingFunctions` +property should now be used instead for the `EscapeOutput` sniff. +- The `WordPress.Arrays.ArrayDeclaration` sniff to give errors for `NoSpaceAfterOpenParenthesis`, `SpaceAfterArrayOpener`, and `SpaceAfterArrayCloser`, instead of warnings. +- The `WordPress.NamingConventions.ValidFunctionName` sniff to allow camelCase method names in classes that implement interfaces. + +### Fixed +- The `WordPress.VIP.ValidatedSanitizedInput` sniff not reporting missing validation when reporting missing sanitization. +- The `WordPress.VIP.ValidatedSanitizedInput` sniff flagging superglobals as needing sanitization when they were only being used in a comparison using `if` or `switch`, etc. + +## [0.4.0] - 2015-05-01 + +### Added +- Change log file. +- Handling for string-interpolated input variables in the `WordPress.VIP.ValidatedSanitizedInput` sniff. +- Errors for using uncached functions when cached equivalents exist. +- `space_before_colon` setting for the `WordPress.WhiteSpace.ControlStructureSpacing` sniff, for control structures using alternative syntax. Possible values: `'required'`, `'optional'`, `'forbidden'`. +- Support for `sanitization` whitelisting comments for the `WordPress.VIP.ValidatedSanitizedInput` sniff. +- Granular error/warning names for all errors and warnings. +- Handling for ternary conditions in the `WordPress.XSS.EscapeOutput` sniff. +- `die`, `exit`, `printf`, `vprintf`, `wp_die`, `_deprecated_argument`, `_deprecated_function`, `_deprecated_file`, `_doing_it_wrong`, `trigger_error`, and `user_error` to the list of printing functions in the `WordPress.XSS.EscapeOutput` sniff. +- `customPrintingFunctions` setting for the `WordPress.XSS.EscapeOutput` sniff. +- `rawurlencode()` and `wp_parse_id_list()` to the list of "sanitizing" functions in the `WordPress.XSS.EscapeOutput` sniff. +- `json_encode()` to the list of discouraged functions in the `WordPress.PHP.DiscouragedFunctions` sniff, in favor of `wp_json_encode()`. +- `vip_powered_wpcom()` to the list of auto-escaped functions in the `WordPress.XSS.EscapeOutput` sniff. +- `debug_print_backtrace()` and `var_export()` to the list of discouraged functions in the `WordPress.PHP.DiscouragedFunctions` sniff. +- Smart handling for formatting functions (`sprintf()` and `wp_sprintf()`) in the `WordPress.XSS.EscapeOutput` sniff. +- `WordPress.PHP.StrictComparisons` sniff. +- Correct handling of `array_map()` in the `WordPress.VIP.ValidatedSanitizedInput` sniff. +- `$_COOKIE` and `$_FILE` to the list of superglobals flagged by the `WordPress.VIP.ValidatedSanitizedInput` and `WordPress.VIP.SuperGlobalInputUsage` sniffs. +- `$_SERVER` to the list of superglobals flagged by the `WordPress.VIP.SuperGlobalInputUsage` sniff. +- `Squiz.ControlStructures.ControlSignature` sniff to the rulesets. + +### Changed +- `WordPress.Arrays.ArrayKeySpacingRestrictions` sniff to give errors for `NoSpacesAroundArrayKeys` and `SpacesAroundArrayKeys` instead of just warnings. +- `WordPress.NamingConventions.ValidFunctionName` sniff to allow for camel caps method names in child classes. +- `WordPress.XSS.EscapeOutput` sniff to allow for integers (e.g. `echo 5` and `print( -1 )`). + +### Removed +- Errors for mixed key/keyless array elements in the `WordPress.Arrays.ArrayDeclaration` sniff. +- BOM from `WordPress.WhiteSpace.OperatorSpacing` sniff file. +- `$content_width` from the list of non-overwritable globals in the `WordPress.Variables.GlobalVariables` sniff. +- `WordPress.Arrays.ArrayAssignmentRestrictions` sniff from the `WordPress-VIP` ruleset. + +### Fixed +- Incorrect errors for `else` statements using alternative syntax. +- `WordPress.VIP.ValidatedSanitizedInput` sniff not always treating casting as sanitization. +- `WordPress.XSS.EscapeOutput` sniff flagging comments as needing to be escaped. +- `WordPress.XSS.EscapeOutput` sniff not sniffing comma-delimited `echo` arguments after encountering the first escaping function in the statement. +- `WordPress.PHP.YodaConditions` sniff not flagging comparisons to constants or function calls. +- `WordPress.Arrays.ArrayDeclaration` sniff not ignoring doc comments. +- Link to phpStorm instructions in `README.md`. +- Poor performance of the `WordPress.Arrays.ArrayAssignmentRestrictions` sniff. +- Poor performance of the `WordPress.Files.FileName` sniff. + +## [0.3.0] - 2014-12-11 + +See the comparison for full list. + +### Changed +- Use semantic version tags for releases. + +## [2013-10-06] + +See the comparison for full list. + +## 2013-06-11 + +Initial tagged release. + +[Unreleased]: https://github.com/WordPress/WordPress-Coding-Standards/compare/master...HEAD +[2.2.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.1.1...2.2.0 +[2.1.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2.0.0-RC1...2.0.0 +[2.0.0-RC1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.2.1...2.0.0-RC1 +[1.2.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.2.0...1.2.1 +[1.2.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.14.1...1.0.0 +[0.14.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.14.0...0.14.1 +[0.14.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.13.1...0.14.0 +[0.13.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.13.0...0.13.1 +[0.13.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.12.0...0.13.0 +[0.12.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.11.0...0.12.0 +[0.11.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.10.0...0.11.0 +[0.10.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.9.0...0.10.0 +[0.9.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.8.0...0.9.0 +[0.8.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.7.1...0.8.0 +[0.7.1]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.7.0...0.7.1 +[0.7.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.6.0...0.7.0 +[0.6.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.5.0...0.6.0 +[0.5.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.4.0...0.5.0 +[0.4.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/0.3.0...0.4.0 +[0.3.0]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2013-10-06...0.3.0 +[2013-10-06]: https://github.com/WordPress/WordPress-Coding-Standards/compare/2013-06-11...2013-10-06 diff --git a/kirki-composer/wp-coding-standards/wpcs/LICENSE b/kirki-composer/wp-coding-standards/wpcs/LICENSE new file mode 100644 index 000000000..359e1a728 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2009 John Godley and contributors. + +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. diff --git a/kirki-composer/wp-coding-standards/wpcs/README.md b/kirki-composer/wp-coding-standards/wpcs/README.md new file mode 100644 index 000000000..42eda804b --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/README.md @@ -0,0 +1,296 @@ + + + +# WordPress Coding Standards for PHP_CodeSniffer + +* [Introduction](#introduction) +* [Project history](#project-history) +* [Installation](#installation) + + [Requirements](#requirements) + + [Composer](#composer) + + [Standalone](#standalone) +* [Rulesets](#rulesets) + + [Standards subsets](#standards-subsets) + + [Using a custom ruleset](#using-a-custom-ruleset) + + [Customizing sniff behaviour](#customizing-sniff-behaviour) + + [Recommended additional rulesets](#recommended-additional-rulesets) +* [How to use](#how-to-use) + + [Command line](#command-line) + + [Using PHPCS and WPCS from within your IDE](#using-phpcs-and-wpcs-from-within-your-ide) +* [Running your code through WPCS automatically using CI tools](#running-your-code-through-wpcs-automatically-using-ci-tools) + + [Travis CI](#travis-ci) +* [Fixing errors or whitelisting them](#fixing-errors-or-whitelisting-them) + + [Tools shipped with WPCS](#tools-shipped-with-wpcs) +* [Contributing](#contributing) +* [License](#license) + +## Introduction + +This project is a collection of [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) rules (sniffs) to validate code developed for WordPress. It ensures code quality and adherence to coding conventions, especially the official [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/). + +## Project history + + - On 22nd April 2009, the original project from [Urban Giraffe](https://urbangiraffe.com/articles/wordpress-codesniffer-standard/) was packaged and published. + - In May 2011 the project was forked and [added](https://github.com/WordPress/WordPress-Coding-Standards/commit/04fd547c691ca2baae3fa8e195a46b0c9dd671c5) to GitHub by [Chris Adams](https://chrisadams.me.uk/). + - In April 2012 [XWP](https://xwp.co/) started to dedicate resources to develop and lead the creation of the sniffs and rulesets for `WordPress-Core`, `WordPress-VIP` (WordPress.com VIP), and `WordPress-Extra`. + - In May 2015, an initial documentation ruleset was [added](https://github.com/WordPress/WordPress-Coding-Standards/commit/b1a4bf8232a22563ef66f8a529357275a49f47dc#diff-a17c358c3262a26e9228268eb0a7b8c8) as `WordPress-Docs`. + - In 2015, [J.D. Grimes](https://github.com/JDGrimes) began significant contributions, along with maintenance from [Gary Jones](https://github.com/GaryJones). + - In 2016, [Juliette Reinders Folmer](https://github.com/jrfnl) began contributing heavily, adding more commits in a year than anyone else in the five years since the project was added to GitHub. + - In July 2018, version [`1.0.0`](https://github.com/WordPress/WordPress-Coding-Standards/releases/tag/1.0.0) of the project was released. + +## Installation + +### Requirements + +The WordPress Coding Standards require PHP 5.4 or higher and [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) version **3.3.1** or higher. + +### Composer + +Standards can be installed with the [Composer](https://getcomposer.org/) dependency manager: + + composer create-project wp-coding-standards/wpcs --no-dev + +Running this command will: + +1. Install WordPress standards into `wpcs` directory. +2. Install PHP_CodeSniffer. +3. Register WordPress standards in PHP_CodeSniffer configuration. +4. Make `phpcs` command available from `wpcs/vendor/bin`. + +For the convenience of using `phpcs` as a global command, you may want to add the path to the `wpcs/vendor/bin` directory to a `PATH` environment variable for your operating system. + +#### Installing WPCS as a dependency + +When installing the WordPress Coding Standards as a dependency in a larger project, the above mentioned step 3 will not be executed automatically. + +There are two actively maintained Composer plugins which can handle the registration of standards with PHP_CodeSniffer for you: +* [composer-phpcodesniffer-standards-plugin](https://github.com/higidi/composer-phpcodesniffer-standards-plugin) +* [phpcodesniffer-composer-installer](https://github.com/DealerDirect/phpcodesniffer-composer-installer):"^0.6" + +It is strongly suggested to `require` one of these plugins in your project to handle the registration of external standards with PHPCS for you. + +### Standalone + +1. Install PHP_CodeSniffer by following its [installation instructions](https://github.com/squizlabs/PHP_CodeSniffer#installation) (via Composer, Phar file, PEAR, or Git checkout). + + Do ensure that PHP_CodeSniffer's version matches our [requirements](#requirements), if, for example, you're using [VVV](https://github.com/Varying-Vagrant-Vagrants/VVV). + +2. Clone the WordPress standards repository: + + git clone -b master https://github.com/WordPress/WordPress-Coding-Standards.git wpcs + +3. Add its path to the PHP_CodeSniffer configuration: + + phpcs --config-set installed_paths /path/to/wpcs + + **Pro-tip:** Alternatively, you can tell PHP_CodeSniffer the path to the WordPress standards by adding the following snippet to your custom ruleset: + ```xml + + ``` + +To summarize: + +```bash +cd ~/projects +git clone https://github.com/squizlabs/PHP_CodeSniffer.git phpcs +git clone -b master https://github.com/WordPress/WordPress-Coding-Standards.git wpcs +cd phpcs +./bin/phpcs --config-set installed_paths ../wpcs +``` + +And then add the `~/projects/phpcs/bin` directory to your `PATH` environment variable via your `.bashrc`. + +You should then see `WordPress-Core` et al listed when you run `phpcs -i`. + +## Rulesets + +### Standards subsets + +The project encompasses a super-set of the sniffs that the WordPress community may need. If you use the `WordPress` standard you will get all the checks. + +You can use the following as standard names when invoking `phpcs` to select sniffs, fitting your needs: + +* `WordPress` - complete set with all of the sniffs in the project + - `WordPress-Core` - main ruleset for [WordPress core coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/) + - `WordPress-Docs` - additional ruleset for [WordPress inline documentation standards](https://make.wordpress.org/core/handbook/best-practices/inline-documentation-standards/) + - `WordPress-Extra` - extended ruleset for recommended best practices, not sufficiently covered in the WordPress core coding standards + - includes `WordPress-Core` + +**Note:** The WPCS package used to include a `WordPress-VIP` ruleset and associated sniffs, prior to WPCS 2.0.0. +The `WordPress-VIP` ruleset was originally intended to aid with the [WordPress.com VIP coding requirements](https://vip.wordpress.com/documentation/vip-go/code-review-blockers-warnings-notices/), but has been superseded. It is recommended to use the [official VIP coding standards](https://github.com/Automattic/VIP-Coding-Standards) ruleset instead for checking code against the VIP platform requirements. + +### Using a custom ruleset + +If you need to further customize the selection of sniffs for your project - you can create a custom ruleset file. When you name this file either `.phpcs.xml`, `phpcs.xml`, `.phpcs.xml.dist` or `phpcs.xml.dist`, PHP_CodeSniffer will automatically locate it as long as it is placed in the directory from which you run the CodeSniffer or in a directory above it. If you follow these naming conventions you don't have to supply a `--standard` arg. For more info, read about [using a default configuration file](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file). See also provided [`phpcs.xml.dist.sample`](phpcs.xml.dist.sample) file and [fully annotated example](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml) in the PHP_CodeSniffer documentation. + +### Customizing sniff behaviour + +The WordPress Coding Standard contains a number of sniffs which are configurable. This means that you can turn parts of the sniff on or off, or change the behaviour by setting a property for the sniff in your custom `.phpcs.xml.dist` file. + +You can find a complete list of all the properties you can change in the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties). + +### Recommended additional rulesets + +The [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) ruleset and its subset [PHPCompatibilityWP](https://github.com/PHPCompatibility/PHPCompatibilityWP) come highly recommended. +The [PHPCompatibility](https://github.com/PHPCompatibility/PHPCompatibility) sniffs are designed to analyse your code for cross-PHP version compatibility. + +The [PHPCompatibilityWP](https://github.com/PHPCompatibility/PHPCompatibilityWP) ruleset is based on PHPCompatibility, but specifically crafted to prevent false positives for projects which expect to run within the context of WordPress, i.e. core, plugins and themes. + +Install either as a separate ruleset and run it separately against your code or add it to your custom ruleset, like so: +```xml + + + *\.php$ + +``` + +Whichever way you run it, do make sure you set the `testVersion` to run the sniffs against. The `testVersion` determines for which PHP versions you will receive compatibility information. The recommended setting for this at this moment is `5.2-` to support the same PHP versions as WordPress Core supports. + +For more information about setting the `testVersion`, see: +* [PHPCompatibility: Sniffing your code for compatibility with specific PHP version(s)](https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions) +* [PHPCompatibility: Using a custom ruleset](https://github.com/PHPCompatibility/PHPCompatibility#using-a-custom-ruleset) + +## How to use + +### Command line + +Run the `phpcs` command line tool on a given file or directory, for example: + + phpcs --standard=WordPress wp-load.php + +Will result in following output: + + ------------------------------------------------------------------------------------------ + FOUND 8 ERRORS AND 10 WARNINGS AFFECTING 11 LINES + ------------------------------------------------------------------------------------------ + 24 | WARNING | [ ] error_reporting() can lead to full path disclosure. + 24 | WARNING | [ ] error_reporting() found. Changing configuration at runtime is rarely + | | necessary. + 37 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 39 | WARNING | [ ] Silencing errors is discouraged + 39 | WARNING | [ ] Silencing errors is discouraged + 42 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 46 | ERROR | [ ] Inline comments must end in full-stops, exclamation marks, or + | | question marks + 46 | ERROR | [x] There must be no blank line following an inline comment + 49 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 54 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 63 | WARNING | [ ] Detected access of super global var $_SERVER, probably needs manual + | | inspection. + 63 | ERROR | [ ] Detected usage of a non-validated input variable: $_SERVER + 63 | ERROR | [ ] Missing wp_unslash() before sanitization. + 63 | ERROR | [ ] Detected usage of a non-sanitized input variable: $_SERVER + 69 | WARNING | [x] "require_once" is a statement not a function; no parentheses are + | | required + 74 | ERROR | [ ] Inline comments must end in full-stops, exclamation marks, or + | | question marks + 92 | ERROR | [ ] All output should be run through an escaping function (see the + | | Security sections in the WordPress Developer Handbooks), found + | | '$die'. + 92 | ERROR | [ ] All output should be run through an escaping function (see the + | | Security sections in the WordPress Developer Handbooks), found '__'. + ------------------------------------------------------------------------------------------ + PHPCBF CAN FIX THE 6 MARKED SNIFF VIOLATIONS AUTOMATICALLY + ------------------------------------------------------------------------------------------ + +### Using PHPCS and WPCS from within your IDE + +* **PhpStorm** : Please see "[PHP Code Sniffer with WordPress Coding Standards Integration](https://confluence.jetbrains.com/display/PhpStorm/WordPress+Development+using+PhpStorm#WordPressDevelopmentusingPhpStorm-PHPCodeSnifferwithWordPressCodingStandardsIntegrationinPhpStorm)" in the PhpStorm documentation. +* **Sublime Text** : Please see "[Setting up WPCS to work in Sublime Text](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Setting-up-WPCS-to-work-in-Sublime-Text)" in the wiki. +* **Atom**: Please see "[Setting up WPCS to work in Atom](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Setting-up-WPCS-to-work-in-Atom)" in the wiki. +* **Visual Studio**: Please see "[Setting up PHP CodeSniffer in Visual Studio Code](https://tommcfarlin.com/php-codesniffer-in-visual-studio-code/)", a tutorial by Tom McFarlin. +* **Eclipse with XAMPP**: Please see "[Setting up WPCS when using Eclipse with XAMPP](https://github.com/WordPress/WordPress-Coding-Standards/wiki/How-to-use-WPCS-with-Eclipse-and-XAMPP)" in the wiki. + + +## Running your code through WPCS automatically using CI tools + +### [Travis CI](https://travis-ci.com/) + +To integrate PHPCS with WPCS with Travis CI, you'll need to install both `before_install` and add the run command to the `script`. +If your project uses Composer, the typical instructions might be different. + +If you use a matrix setup in Travis to test your code against different PHP and/or WordPress versions, you don't need to run PHPCS on each variant of the matrix as the results will be same. +You can set an environment variable in the Travis matrix to only run the sniffs against one setup in the matrix. + +#### Travis CI example +```yaml +language: php + +matrix: + include: + # Arbitrary PHP version to run the sniffs against. + - php: '7.0' + env: SNIFF=1 + +before_install: + - if [[ "$SNIFF" == "1" ]]; then export PHPCS_DIR=/tmp/phpcs; fi + - if [[ "$SNIFF" == "1" ]]; then export SNIFFS_DIR=/tmp/sniffs; fi + # Install PHP_CodeSniffer. + - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/squizlabs/PHP_CodeSniffer.git $PHPCS_DIR; fi + # Install WordPress Coding Standards. + - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/WordPress/WordPress-Coding-Standards.git $SNIFFS_DIR; fi + # Set install path for WordPress Coding Standards. + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs --config-set installed_paths $SNIFFS_DIR; fi + # After CodeSniffer install you should refresh your path. + - if [[ "$SNIFF" == "1" ]]; then phpenv rehash; fi + +script: + # Run against WordPress Coding Standards. + # If you use a custom ruleset, change `--standard=WordPress` to point to your ruleset file, + # for example: `--standard=wpcs.xml`. + # You can use any of the normal PHPCS command line arguments in the command: + # https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs -p . --standard=WordPress; fi +``` + +More examples and advice about integrating PHPCS in your Travis build tests can be found here: https://github.com/jrfnl/make-phpcs-work-for-you/tree/master/travis-examples + + +## Fixing errors or whitelisting them + +You can find information on how to deal with some of the more frequent issues in the [wiki](https://github.com/WordPress/WordPress-Coding-Standards/wiki). + +### Tools shipped with WPCS + +Since version 1.2.0, WPCS has a special sniff category `Utils`. + +This sniff category contains some tools which, generally speaking, will only be needed to be run once over a codebase and for which the fixers can be considered _risky_, i.e. very careful review by a developer is needed before accepting the fixes made by these sniffs. + +The sniffs in this category are disabled by default and can only be activated by adding some properties for each sniff via a custom ruleset. + +At this moment, WPCS offer the following tools: +* `WordPress.Utils.I18nTextDomainFixer` - This sniff can replace the text domain used in a code-base. + The sniff will fix the text domains in both I18n function calls as well as in a plugin/theme header. + Passing the following properties will activate the sniff: + - `old_text_domain`: an array with one or more (old) text domain names which need to be replaced; + - `new_text_domain`: the correct (new) text domain as a string. + + +## Contributing + +See [CONTRIBUTING](.github/CONTRIBUTING.md), including information about [unit testing](.github/CONTRIBUTING.md#unit-testing) the standard. + +## License + +See [LICENSE](LICENSE) (MIT). diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml new file mode 100644 index 000000000..0bff5a0d4 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress-Core/ruleset.xml @@ -0,0 +1,529 @@ + + + + Non-controversial generally-agreed upon WordPress Coding Standards + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + The "goto" language construct should not be used. + + + + + error + eval() is a security risk so not allowed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml new file mode 100644 index 000000000..e16001ed7 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress-Docs/ruleset.xml @@ -0,0 +1,109 @@ + + + + WordPress Coding Standards for Inline Documentation and Comments + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml new file mode 100644 index 000000000..4a2f95997 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress-Extra/ruleset.xml @@ -0,0 +1,187 @@ + + + + Best practices beyond core WordPress Coding Standards + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + warning + + + warning + + + warning + + + + + + + + + + + + warning + Best practice suggestion: Declare only one class/interface/trait in a file. + + + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + + + error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php new file mode 100644 index 000000000..7c662cd0f --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractArrayAssignmentRestrictionsSniff.php @@ -0,0 +1,240 @@ +setup_groups() ) { + return array(); + } + + return array( + \T_DOUBLE_ARROW, + \T_CLOSE_SQUARE_BRACKET, + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + ); + } + + /** + * Groups of variables to restrict. + * + * This method should be overridden in extending classes. + * + * Example: groups => array( + * 'groupname' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'keys' => array( 'key1', 'another_key' ), + * 'callback' => array( 'class', 'method' ), // Optional. + * ) + * ) + * + * @return array + */ + abstract public function getGroups(); + + /** + * Cache the groups. + * + * @since 0.13.0 + * + * @return bool True if the groups were setup. False if not. + */ + protected function setup_groups() { + $this->groups_cache = $this->getGroups(); + + if ( empty( $this->groups_cache ) && empty( self::$groups ) ) { + return false; + } + + // Allow for adding extra unit tests. + if ( ! empty( self::$groups ) ) { + $this->groups_cache = array_merge( $this->groups_cache, self::$groups ); + } + + return true; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $this->excluded_groups = $this->merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups_cache, $this->excluded_groups ) === array() ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + $token = $this->tokens[ $stackPtr ]; + + if ( \T_CLOSE_SQUARE_BRACKET === $token['code'] ) { + $equal = $this->phpcsFile->findNext( \T_WHITESPACE, ( $stackPtr + 1 ), null, true ); + if ( \T_EQUAL !== $this->tokens[ $equal ]['code'] ) { + return; // This is not an assignment! + } + } + + // Instances: Multi-dimensional array, keyed by line. + $inst = array(); + + /* + * Covers: + * $foo = array( 'bar' => 'taz' ); + * $foo['bar'] = $taz; + */ + if ( \in_array( $token['code'], array( \T_CLOSE_SQUARE_BRACKET, \T_DOUBLE_ARROW ), true ) ) { + $operator = $stackPtr; // T_DOUBLE_ARROW. + if ( \T_CLOSE_SQUARE_BRACKET === $token['code'] ) { + $operator = $this->phpcsFile->findNext( \T_EQUAL, ( $stackPtr + 1 ) ); + } + + $keyIdx = $this->phpcsFile->findPrevious( array( \T_WHITESPACE, \T_CLOSE_SQUARE_BRACKET ), ( $operator - 1 ), null, true ); + if ( ! is_numeric( $this->tokens[ $keyIdx ]['content'] ) ) { + $key = $this->strip_quotes( $this->tokens[ $keyIdx ]['content'] ); + $valStart = $this->phpcsFile->findNext( array( \T_WHITESPACE ), ( $operator + 1 ), null, true ); + $valEnd = $this->phpcsFile->findNext( array( \T_COMMA, \T_SEMICOLON ), ( $valStart + 1 ), null, false, null, true ); + $val = $this->phpcsFile->getTokensAsString( $valStart, ( $valEnd - $valStart ) ); + $val = $this->strip_quotes( $val ); + $inst[ $key ][] = array( $val, $token['line'] ); + } + } elseif ( \in_array( $token['code'], array( \T_CONSTANT_ENCAPSED_STRING, \T_DOUBLE_QUOTED_STRING ), true ) ) { + // $foo = 'bar=taz&other=thing'; + if ( preg_match_all( '#(?:^|&)([a-z_]+)=([^&]*)#i', $this->strip_quotes( $token['content'] ), $matches ) <= 0 ) { + return; // No assignments here, nothing to check. + } + foreach ( $matches[1] as $i => $_k ) { + $inst[ $_k ][] = array( $matches[2][ $i ], $token['line'] ); + } + } + + if ( empty( $inst ) ) { + return; + } + + foreach ( $this->groups_cache as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + $callback = ( isset( $group['callback'] ) && is_callable( $group['callback'] ) ) ? $group['callback'] : array( $this, 'callback' ); + + foreach ( $inst as $key => $assignments ) { + foreach ( $assignments as $occurance ) { + list( $val, $line ) = $occurance; + + if ( ! \in_array( $key, $group['keys'], true ) ) { + continue; + } + + $output = \call_user_func( $callback, $key, $val, $line, $group ); + + if ( ! isset( $output ) || false === $output ) { + continue; + } elseif ( true === $output ) { + $message = $group['message']; + } else { + $message = $output; + } + + $this->addMessage( + $message, + $stackPtr, + ( 'error' === $group['type'] ), + $this->string_to_errorcode( $groupName . '_' . $key ), + array( $key, $val ) + ); + } + } + } + } + + /** + * Callback to process each confirmed key, to check value. + * + * This method must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + abstract public function callback( $key, $val, $line, $group ); + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php new file mode 100644 index 000000000..9374622e1 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractClassRestrictionsSniff.php @@ -0,0 +1,245 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Avoid direct calls to the database.', + * 'classes' => array( 'PDO', '\Namespace\Classname' ), + * ) + * ) + * + * You can use * wildcards to target a group of (namespaced) classes. + * Aliased namespaces (use ..) are currently not supported. + * + * Documented here for clarity. Not (re)defined as it is already defined in the parent class. + * + * @return array + * + abstract public function getGroups(); + */ + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + // Prepare the function group regular expressions only once. + if ( false === $this->setup_groups( 'classes' ) ) { + return array(); + } + + return array( + \T_DOUBLE_COLON, + \T_NEW, + \T_EXTENDS, + \T_IMPLEMENTS, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * {@internal Unlike in the `AbstractFunctionRestrictionsSniff`, + * we can't do a preliminary check on classes as at this point + * we don't know the class name yet.}} + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + // Reset the temporary storage before processing the token. + unset( $this->classname ); + + $this->excluded_groups = $this->merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups, $this->excluded_groups ) === array() ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + if ( true === $this->is_targetted_token( $stackPtr ) ) { + return $this->check_for_matches( $stackPtr ); + } + } + + /** + * Determine if we have a valid classname for the target token. + * + * @since 0.11.0 This logic was originally contained in the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + public function is_targetted_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + $classname = ''; + + if ( \in_array( $token['code'], array( \T_NEW, \T_EXTENDS, \T_IMPLEMENTS ), true ) ) { + if ( \T_NEW === $token['code'] ) { + $nameEnd = ( $this->phpcsFile->findNext( array( \T_OPEN_PARENTHESIS, \T_WHITESPACE, \T_SEMICOLON, \T_OBJECT_OPERATOR ), ( $stackPtr + 2 ) ) - 1 ); + } else { + $nameEnd = ( $this->phpcsFile->findNext( array( \T_CLOSE_CURLY_BRACKET, \T_WHITESPACE ), ( $stackPtr + 2 ) ) - 1 ); + } + + $length = ( $nameEnd - ( $stackPtr + 1 ) ); + $classname = $this->phpcsFile->getTokensAsString( ( $stackPtr + 2 ), $length ); + + if ( \T_NS_SEPARATOR !== $this->tokens[ ( $stackPtr + 2 ) ]['code'] ) { + $classname = $this->get_namespaced_classname( $classname, ( $stackPtr - 1 ) ); + } + } + + if ( \T_DOUBLE_COLON === $token['code'] ) { + $nameEnd = $this->phpcsFile->findPrevious( \T_STRING, ( $stackPtr - 1 ) ); + $nameStart = ( $this->phpcsFile->findPrevious( array( \T_STRING, \T_NS_SEPARATOR, \T_NAMESPACE ), ( $nameEnd - 1 ), null, true, null, true ) + 1 ); + $length = ( $nameEnd - ( $nameStart - 1 ) ); + $classname = $this->phpcsFile->getTokensAsString( $nameStart, $length ); + + if ( \T_NS_SEPARATOR !== $this->tokens[ $nameStart ]['code'] ) { + $classname = $this->get_namespaced_classname( $classname, ( $nameStart - 1 ) ); + } + } + + // Stop if we couldn't determine a classname. + if ( empty( $classname ) ) { + return false; + } + + // Nothing to do if 'parent', 'self' or 'static'. + if ( \in_array( $classname, array( 'parent', 'self', 'static' ), true ) ) { + return false; + } + + $this->classname = $classname; + return true; + } + + /** + * Verify if the current token is one of the targetted classes. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function check_for_matches( $stackPtr ) { + $skip_to = array(); + + foreach ( $this->groups as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + if ( preg_match( $group['regex'], $this->classname ) === 1 ) { + $skip_to[] = $this->process_matched_token( $stackPtr, $groupName, $this->classname ); + } + } + + if ( empty( $skip_to ) || min( $skip_to ) === 0 ) { + return; + } + + return min( $skip_to ); + } + + /** + * Prepare the class name for use in a regular expression. + * + * The getGroups() method allows for providing class names with a wildcard * to target + * a group of classes within a namespace. It also allows for providing class names as + * 'ordinary' names or prefixed with one or more namespaces. + * This prepare routine takes that into account while still safely escaping the + * class name for use in a regular expression. + * + * @param string $classname Class name, potentially prefixed with namespaces. + * @return string Regex escaped class name. + */ + protected function prepare_name_for_regex( $classname ) { + $classname = trim( $classname, '\\' ); // Make sure all classnames have a \ prefix, but only one. + return parent::prepare_name_for_regex( $classname ); + } + + /** + * See if the classname was found in a namespaced file and if so, add the namespace to the classname. + * + * @param string $classname The full classname as found. + * @param int $search_from The token position to search up from. + * @return string Classname, potentially prefixed with the namespace. + */ + protected function get_namespaced_classname( $classname, $search_from ) { + // Don't do anything if this is already a fully qualified classname. + if ( empty( $classname ) || '\\' === $classname[0] ) { + return $classname; + } + + // Remove the namespace keyword if used. + if ( 0 === strpos( $classname, 'namespace\\' ) ) { + $classname = substr( $classname, 10 ); + } + + $namespace_keyword = $this->phpcsFile->findPrevious( \T_NAMESPACE, $search_from ); + if ( false === $namespace_keyword ) { + // No namespace keyword found at all, so global namespace. + $classname = '\\' . $classname; + } else { + $namespace = $this->determine_namespace( $search_from ); + + if ( ! empty( $namespace ) ) { + $classname = '\\' . $namespace . '\\' . $classname; + } else { + // No actual namespace found, so global namespace. + $classname = '\\' . $classname; + } + } + + return $classname; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php new file mode 100644 index 000000000..ab68a1dcf --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionParameterSniff.php @@ -0,0 +1,112 @@ +target_functions ) ) { + return array(); + } + + return array( + $this->group_name => array( + 'functions' => array_keys( $this->target_functions ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $parameters = $this->get_function_call_parameters( $stackPtr ); + + if ( empty( $parameters ) ) { + return $this->process_no_parameters( $stackPtr, $group_name, $matched_content ); + } else { + return $this->process_parameters( $stackPtr, $group_name, $matched_content, $parameters ); + } + } + + /** + * Process the parameters of a matched function. + * + * This method has to be made concrete in child classes. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + abstract public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ); + + /** + * Process the function if no parameters were found. + * + * Defaults to doing nothing. Can be overloaded in child classes to handle functions + * were parameters are expected, but none found. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_no_parameters( $stackPtr, $group_name, $matched_content ) { + return; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php new file mode 100644 index 000000000..53ea9a255 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/AbstractFunctionRestrictionsSniff.php @@ -0,0 +1,342 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function', 'mysql_*' ), + * // Only useful when using wildcards: + * 'whitelist' => array( 'mysql_to_rfc3339' => true, ), + * ) + * ) + * + * You can use * wildcards to target a group of functions. + * When you use * wildcards, you may inadvertently restrict too many + * functions. In that case you can add the `whitelist` key to + * whitelist individual functions to prevent false positives. + * + * @return array + */ + abstract public function getGroups(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + // Prepare the function group regular expressions only once. + if ( false === $this->setup_groups( 'functions' ) ) { + return array(); + } + + return array( + \T_STRING, + ); + } + + /** + * Set up the regular expressions for each group. + * + * @since 0.10.0 + * + * @param string $key The group array index key where the input for the regular expression can be found. + * @return bool True if the groups were setup. False if not. + */ + protected function setup_groups( $key ) { + // Prepare the function group regular expressions only once. + $this->groups = $this->getGroups(); + + if ( empty( $this->groups ) && empty( self::$unittest_groups ) ) { + return false; + } + + // Allow for adding extra unit tests. + if ( ! empty( self::$unittest_groups ) ) { + $this->groups = array_merge( $this->groups, self::$unittest_groups ); + } + + $all_items = array(); + foreach ( $this->groups as $groupName => $group ) { + if ( empty( $group[ $key ] ) ) { + unset( $this->groups[ $groupName ] ); + } else { + $items = array_map( array( $this, 'prepare_name_for_regex' ), $group[ $key ] ); + $all_items[] = $items; + $items = implode( '|', $items ); + + $this->groups[ $groupName ]['regex'] = sprintf( $this->regex_pattern, $items ); + } + } + + if ( empty( $this->groups ) ) { + return false; + } + + // Create one "super-regex" to allow for initial filtering. + $all_items = \call_user_func_array( 'array_merge', $all_items ); + $all_items = implode( '|', array_unique( $all_items ) ); + $this->prelim_check_regex = sprintf( $this->regex_pattern, $all_items ); + + return true; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + $this->excluded_groups = $this->merge_custom_array( $this->exclude ); + if ( array_diff_key( $this->groups, $this->excluded_groups ) === array() ) { + // All groups have been excluded. + // Don't remove the listener as the exclude property can be changed inline. + return; + } + + // Preliminary check. If the content of the T_STRING is not one of the functions we're + // looking for, we can bow out before doing the heavy lifting of checking whether + // this is a function call. + if ( preg_match( $this->prelim_check_regex, $this->tokens[ $stackPtr ]['content'] ) !== 1 ) { + return; + } + + if ( true === $this->is_targetted_token( $stackPtr ) ) { + return $this->check_for_matches( $stackPtr ); + } + } + + /** + * Verify is the current token is a function call. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return bool + */ + public function is_targetted_token( $stackPtr ) { + + if ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + // Exclude function definitions, class methods, and namespaced calls. + if ( $this->is_class_object_call( $stackPtr ) === true ) { + return false; + } + + if ( $this->is_token_namespaced( $stackPtr ) === true ) { + return false; + } + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false !== $prev ) { + // Skip sniffing on function, class definitions or for function aliases in use statements. + $skipped = array( + \T_FUNCTION => \T_FUNCTION, + \T_CLASS => \T_CLASS, + \T_AS => \T_AS, // Use declaration alias. + ); + + if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) { + return false; + } + } + + // Check if this could even be a function call. + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false === $next ) { + return false; + } + + // Check for `use function ... (as|;)`. + if ( ( \T_STRING === $this->tokens[ $prev ]['code'] && 'function' === $this->tokens[ $prev ]['content'] ) + && ( \T_AS === $this->tokens[ $next ]['code'] || \T_SEMICOLON === $this->tokens[ $next ]['code'] ) + ) { + return true; + } + + // If it's not a `use` statement, there should be parenthesis. + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $next ]['code'] ) { + return false; + } + + return true; + } + + /** + * Verify if the current token is one of the targetted functions. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function check_for_matches( $stackPtr ) { + $token_content = strtolower( $this->tokens[ $stackPtr ]['content'] ); + $skip_to = array(); + + foreach ( $this->groups as $groupName => $group ) { + + if ( isset( $this->excluded_groups[ $groupName ] ) ) { + continue; + } + + if ( isset( $group['whitelist'][ $token_content ] ) ) { + continue; + } + + if ( preg_match( $group['regex'], $token_content ) === 1 ) { + $skip_to[] = $this->process_matched_token( $stackPtr, $groupName, $token_content ); + } + } + + if ( empty( $skip_to ) || min( $skip_to ) === 0 ) { + return; + } + + return min( $skip_to ); + } + + /** + * Process a matched token. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->addMessage( + $this->groups[ $group_name ]['message'], + $stackPtr, + ( 'error' === $this->groups[ $group_name ]['type'] ), + $this->string_to_errorcode( $group_name . '_' . $matched_content ), + array( $matched_content ) + ); + } + + /** + * Prepare the function name for use in a regular expression. + * + * The getGroups() method allows for providing function names with a wildcard * to target + * a group of functions. This prepare routine takes that into account while still safely + * escaping the function name for use in a regular expression. + * + * @since 0.10.0 + * + * @param string $function Function name. + * @return string Regex escaped function name. + */ + protected function prepare_name_for_regex( $function ) { + $function = str_replace( array( '.*', '*' ), '@@', $function ); // Replace wildcards with placeholder. + $function = preg_quote( $function, '`' ); + $function = str_replace( '@@', '.*', $function ); // Replace placeholder with regex wildcard. + + return $function; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml new file mode 100644 index 000000000..5b9a1deea --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayIndentationStandard.xml @@ -0,0 +1,112 @@ + + + + + + + 22, +); + ]]> + + + 22, + ); + ]]> + + + + + + + + 22, + 'comment_count' => array( + 'value' => 25, + 'compare' => '>=', + ), + 'post_type' => array( + 'post', + 'page', + ), +); + ]]> + + + 22, + 'comment_count' => array( + 'value' => 25, + 'compare' => '>=', + ), + 'post_type' => array( + 'post', + 'page', + ), +); + ]]> + + + + + + + + 'start of phrase' + . 'concatented additional phrase' + . 'more text', +); + ]]> + + + 'start of phrase' +. 'concatented additional phrase' +. 'more text', +); + ]]> + + + + + + + + << + start of phrase + concatented additional phrase + more text +EOD +, +); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml new file mode 100644 index 000000000..c1e27a132 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/ArrayKeySpacingRestrictionsStandard.xml @@ -0,0 +1,27 @@ + + + + + + + [ $post_id ]; +$post_title = $post[ 'concatenated' . $title ]; +$post = $posts[ HOME_PAGE ]; +$post = $posts[123]; +$post_title = $post['post_title']; + ]]> + + + [$post_id]; +$post_title = $post['concatenated' . $title ]; +$post = $posts[HOME_PAGE]; +$post = $posts[ 123 ]; +$post_title = $post[ 'post_title' ]; + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml new file mode 100644 index 000000000..b3f87cbbe --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Arrays/MultipleStatementAlignmentStandard.xml @@ -0,0 +1,46 @@ + + + + + + + => 22 ); +$bar = array( 'year' => $current_year ); + ]]> + + + =>22 ); +$bar = array( 'year'=> $current_year ); + ]]> + + + + + + + + => 22, + 'year' => $current_year, + 'monthnum' => $current_month, +); + ]]> + + + => 22, + 'year' => $current_year, + 'monthnum' => $current_month, +); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml new file mode 100644 index 000000000..cdd749ecd --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Classes/ClassInstantiationStandard.xml @@ -0,0 +1,53 @@ + + + + + + + (); + ]]> + + + + + + + + + + + + + + (); + ]]> + + + + + + + + new Foobar(); + ]]> + + + & new Foobar(); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml new file mode 100644 index 000000000..3755a3c96 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/CodeAnalysis/EscapedNotTranslatedStandard.xml @@ -0,0 +1,20 @@ + + + + + + + esc_html__( 'text', 'domain' ); + ]]> + + + esc_html( 'text', 'domain' ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml new file mode 100644 index 000000000..add8ed237 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/DateTime/CurrentTimeTimestampStandard.xml @@ -0,0 +1,31 @@ + + + + + + + time(); + ]]> + + + current_time( 'timestamp', true ); + ]]> + + + + + 'Y-m-d' ); + ]]> + + + current_time( 'U', false ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml new file mode 100644 index 000000000..479dbd9ba --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidHookNameStandard.xml @@ -0,0 +1,32 @@ + + + + + + + + 'prefix_hook_name', $var ); + ]]> + + + 'Prefix_Hook_NAME', $var ); + ]]> + + + + + 'prefix_hook_name', $var ); + ]]> + + + 'prefix\hook-name', $var ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml new file mode 100644 index 000000000..86be1bbee --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml @@ -0,0 +1,117 @@ + + + + + + + 'my_short_slug', + array() +); + ]]> + + + 'my_own_post_type_too_long', + array() +); + ]]> + + + + + + + + 'my_post_type_slug', + array() +); + ]]> + + + 'my/post/type/slug', + array() +); + ]]> + + + + + + + + 'my_post_active', + array() +); + ]]> + + + "my_post_{$status}", + array() +); + ]]> + + + + + + + + 'prefixed_author', + array() +); + ]]> + + + 'author', + array() +); + ]]> + + + + + + + + 'prefixed_author', + array() +); + ]]> + + + 'wp_author', + array() +); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml new file mode 100644 index 000000000..c81b2fd82 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/DisallowShortTernaryStandard.xml @@ -0,0 +1,20 @@ + + + + + + + ? + $data['height'] : 0; + ]]> + + + ? : 0; + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml new file mode 100644 index 000000000..dfc74e912 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/PHP/IniSetStandard.xml @@ -0,0 +1,36 @@ + + + + + + + + + + 'short_open_tag', 'off' ); + ]]> + + + + + + + + wp_raise_memory_limit(); + ]]> + + + 'memory_limit', '256M' ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml new file mode 100644 index 000000000..c2bcf5b8b --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/Security/SafeRedirectStandard.xml @@ -0,0 +1,19 @@ + + + + + + + wp_safe_redirect( $location ); + ]]> + + + wp_redirect( $location ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml new file mode 100644 index 000000000..55a9037d4 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/CronIntervalStandard.xml @@ -0,0 +1,41 @@ + + + + + + + HOUR_IN_SECONDS, + 'display' => __( 'Every hour' ) + ); + return $schedules; +} + +add_filter( + 'cron_schedules', + 'adjust_schedules' +); + ]]> + + + 9 * 60, + 'display' => __( 'Every 9 minutes' ) + ); + return $schedules; +} + +add_filter( + 'cron_schedules', + 'adjust_schedules' +); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml new file mode 100644 index 000000000..4d06f6e35 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedClassesStandard.xml @@ -0,0 +1,19 @@ + + + + + + + WP_User_Query(); + ]]> + + + WP_User_Search(); // Deprecated WP 3.1. + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml new file mode 100644 index 000000000..7fcc9c4e5 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + get_sites(); + ]]> + + + wp_get_sites(); // Deprecated WP 4.6. + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml new file mode 100644 index 000000000..0348fdffe --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParameterValuesStandard.xml @@ -0,0 +1,19 @@ + + + + + + + 'url' ); + ]]> + + + 'home' ); // Deprecated WP 2.2.0. + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml new file mode 100644 index 000000000..6399ca62f --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/DeprecatedParametersStandard.xml @@ -0,0 +1,36 @@ + + + after the deprecated parameter, only ever pass the default value. + ]]> + + + + + + + $string ); + ]]> + + + + + '', 'yes' ); + ]]> + + + 'oops', 'yes' ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml new file mode 100644 index 000000000..3857df3d7 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/EnqueuedResourcesStandard.xml @@ -0,0 +1,53 @@ + + + + + + + wp_enqueue_script( + 'someScript-js', + $path_to_file, + array( 'jquery' ), + '1.0.0', + true +); + ]]> + + + ', + esc_url( $path_to_file ) +); + ]]> + + + + + + + + wp_enqueue_style( + 'style-name', + $path_to_file, + array(), + '1.0.0' +); + ]]> + + + ', + esc_url( $path_to_file ) +); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml new file mode 100644 index 000000000..aa24f740d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WP/PostsPerPageStandard.xml @@ -0,0 +1,69 @@ + + + + + + + -1, +); +$args = array( + 'posts_per_page' => 100, +); +$args = array( + 'posts_per_page' => '10', +); + +$query_args['posts_per_page'] = 100; + +_query_posts( 'nopaging=1&posts_per_page=50' ); + ]]> + + + 101, +); + +$query_args['posts_per_page'] = 200; + +_query_posts( 'nopaging=1&posts_per_page=999' ); + ]]> + + + + + -1, +); +$args = array( + 'numberposts' => 100, +); +$args = array( + 'numberposts' => '10', +); + +$query_args['numberposts'] = '-1'; + +_query_posts( 'numberposts=50' ); + ]]> + + + 101, +); + +$query_args['numberposts'] = '200'; + +_query_posts( 'numberposts=999' ); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml new file mode 100644 index 000000000..8539325b3 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/CastStructureSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + (int) '420'; + +// No space between spread operator and cast. +$a = function_call( ...(array) $mixed ); + ]]> + + + =(int) '420'; + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml new file mode 100644 index 000000000..16f1da2fb --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/DisallowInlineTabsStandard.xml @@ -0,0 +1,25 @@ + + + + + + + [space]=> 'lor', + 'b'[space][space][space]=> 'em', +); + ]]> + + + [tab]=> 'lor', + 'b'[tab]=> 'em', +); + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml new file mode 100644 index 000000000..ca819ffd7 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Docs/WhiteSpace/PrecisionAlignmentStandard.xml @@ -0,0 +1,31 @@ + + + + + + + [tab]$var = true; + ]]> + + + [space][space]$var = true; + ]]> + + + + + [tab][space][space][space][space]$var = true; + ]]> + + + [tab][space][space][space]$var = true; + ]]> + + + diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php new file mode 100644 index 000000000..1599a97a1 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/PHPCSHelper.php @@ -0,0 +1,109 @@ +config->tabWidth ) && $phpcsFile->config->tabWidth > 0 ) { + $tab_width = $phpcsFile->config->tabWidth; + } + + return $tab_width; + } + + /** + * Check whether the `--ignore-annotations` option has been used. + * + * @since 0.13.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile Optional. The current file being processed. + * + * @return bool True if annotations should be ignored, false otherwise. + */ + public static function ignore_annotations( File $phpcsFile = null ) { + if ( isset( $phpcsFile, $phpcsFile->config->annotations ) ) { + return ! $phpcsFile->config->annotations; + } else { + $annotations = Config::getConfigData( 'annotations' ); + if ( isset( $annotations ) ) { + return ! $annotations; + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniff.php new file mode 100644 index 000000000..55ca6e741 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniff.php @@ -0,0 +1,3424 @@ + true`, i.e. the array item is set as the array key. + * This allows for sniffs to verify whether something is in one of these + * lists using `isset()` rather than `in_array()` which is a much more + * efficient (faster) check to execute and therefore improves the + * performance of the sniffs. + * The `true` value in those cases is used as a placeholder and has no + * meaning in and of itself. + * In the rare few cases where the array values *do* have meaning, this + * is documented in the property documentation.}} + */ +abstract class Sniff implements PHPCS_Sniff { + + /** + * Regex to get complex variables from T_DOUBLE_QUOTED_STRING or T_HEREDOC. + * + * @since 0.14.0 + * + * @var string + */ + const REGEX_COMPLEX_VARS = '`(?:(\{)?(?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(?:->\$?(?P>varname)|\[[^\]]+\]|::\$?(?P>varname)|\([^\)]*\))*(?(3)\}|)(?(2)\}|)(?(1)\}|)`'; + + /** + * Minimum supported WordPress version. + * + * Currently used by the `WordPress.WP.AlternativeFunctions`, + * `WordPress.WP.DeprecatedClasses`, `WordPress.WP.DeprecatedFunctions` + * and the `WordPress.WP.DeprecatedParameter` sniff. + * + * These sniffs will throw an error when usage of a deprecated class/function/parameter + * is detected if the class/function/parameter was deprecated before the minimum + * supported WP version; a warning otherwise. + * By default, it is set to presume that a project will support the current + * WP version and up to three releases before. + * + * This property allows changing the minimum supported WP version used by + * these sniffs by setting a property in a custom phpcs.xml ruleset. + * This property will need to be set for each sniff which uses it. + * + * Example usage: + * + * + * + * + * + * + * Alternatively, the value can be passed in one go for all sniff using it via + * the command line or by setting a `` value in a custom phpcs.xml ruleset. + * Note: the `_wp_` in the command line property name! + * + * CL: `phpcs --runtime-set minimum_supported_wp_version 4.5` + * Ruleset: `` + * + * @since 0.14.0 Previously the individual sniffs each contained this property. + * + * @internal When the value of this property is changed, it will also need + * to be changed in the `WP/AlternativeFunctionsUnitTest.inc` file. + * + * @var string WordPress version. + */ + public $minimum_supported_version = '5.1'; + + /** + * Custom list of classes which test classes can extend. + * + * This property allows end-users to add to the $test_class_whitelist via their ruleset. + * This property will need to be set for each sniff which uses the + * `is_test_class()` method. + * Currently the method is used by the `WordPress.WP.GlobalVariablesOverride`, + * `WordPress.NamingConventions.PrefixAllGlobals` and the `WordPress.Files.Filename` sniffs. + * + * Example usage: + * + * + * + * + * + * + * + * + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $custom_test_class_whitelist = array(); + + /** + * List of the functions which verify nonces. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $nonceVerificationFunctions = array( + 'wp_verify_nonce' => true, + 'check_admin_referer' => true, + 'check_ajax_referer' => true, + ); + + /** + * Functions that escape values for display. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $escapingFunctions = array( + 'absint' => true, + 'esc_attr__' => true, + 'esc_attr_e' => true, + 'esc_attr_x' => true, + 'esc_attr' => true, + 'esc_html__' => true, + 'esc_html_e' => true, + 'esc_html_x' => true, + 'esc_html' => true, + 'esc_js' => true, + 'esc_sql' => true, + 'esc_textarea' => true, + 'esc_url_raw' => true, + 'esc_url' => true, + 'filter_input' => true, + 'filter_var' => true, + 'floatval' => true, + 'highlight_string' => true, + 'intval' => true, + 'json_encode' => true, + 'like_escape' => true, + 'number_format' => true, + 'rawurlencode' => true, + 'sanitize_hex_color' => true, + 'sanitize_hex_color_no_hash' => true, + 'sanitize_html_class' => true, + 'sanitize_key' => true, + 'sanitize_user_field' => true, + 'tag_escape' => true, + 'urlencode_deep' => true, + 'urlencode' => true, + 'wp_json_encode' => true, + 'wp_kses_allowed_html' => true, + 'wp_kses_data' => true, + 'wp_kses_post' => true, + 'wp_kses' => true, + ); + + /** + * Functions whose output is automatically escaped for display. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $autoEscapedFunctions = array( + 'allowed_tags' => true, + 'bloginfo' => true, + 'body_class' => true, + 'calendar_week_mod' => true, + 'category_description' => true, + 'checked' => true, + 'comment_class' => true, + 'count' => true, + 'disabled' => true, + 'do_shortcode' => true, + 'do_shortcode_tag' => true, + 'get_archives_link' => true, + 'get_attachment_link' => true, + 'get_avatar' => true, + 'get_bookmark_field' => true, + 'get_calendar' => true, + 'get_comment_author_link' => true, + 'get_current_blog_id' => true, + 'get_delete_post_link' => true, + 'get_search_form' => true, + 'get_search_query' => true, + 'get_the_author_link' => true, + 'get_the_author' => true, + 'get_the_date' => true, + 'get_the_ID' => true, + 'get_the_post_thumbnail' => true, + 'get_the_term_list' => true, + 'post_type_archive_title' => true, + 'readonly' => true, + 'selected' => true, + 'single_cat_title' => true, + 'single_month_title' => true, + 'single_post_title' => true, + 'single_tag_title' => true, + 'single_term_title' => true, + 'tag_description' => true, + 'term_description' => true, + 'the_author' => true, + 'the_date' => true, + 'the_title_attribute' => true, + 'walk_nav_menu_tree' => true, + 'wp_dropdown_categories' => true, + 'wp_dropdown_users' => true, + 'wp_generate_tag_cloud' => true, + 'wp_get_archives' => true, + 'wp_get_attachment_image' => true, + 'wp_get_attachment_link' => true, + 'wp_link_pages' => true, + 'wp_list_authors' => true, + 'wp_list_bookmarks' => true, + 'wp_list_categories' => true, + 'wp_list_comments' => true, + 'wp_login_form' => true, + 'wp_loginout' => true, + 'wp_nav_menu' => true, + 'wp_register' => true, + 'wp_tag_cloud' => true, + 'wp_title' => true, + ); + + /** + * Functions that sanitize values. + * + * This list is complementary to the `$unslashingSanitizingFunctions` + * list. + * Sanitizing functions should be added to this list if they do *not* + * implicitely unslash data and to the `$unslashingsanitizingFunctions` + * list if they do. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $sanitizingFunctions = array( + '_wp_handle_upload' => true, + 'esc_url_raw' => true, + 'filter_input' => true, + 'filter_var' => true, + 'hash_equals' => true, + 'is_email' => true, + 'number_format' => true, + 'sanitize_bookmark_field' => true, + 'sanitize_bookmark' => true, + 'sanitize_email' => true, + 'sanitize_file_name' => true, + 'sanitize_hex_color_no_hash' => true, + 'sanitize_hex_color' => true, + 'sanitize_html_class' => true, + 'sanitize_meta' => true, + 'sanitize_mime_type' => true, + 'sanitize_option' => true, + 'sanitize_sql_orderby' => true, + 'sanitize_term_field' => true, + 'sanitize_term' => true, + 'sanitize_text_field' => true, + 'sanitize_textarea_field' => true, + 'sanitize_title_for_query' => true, + 'sanitize_title_with_dashes' => true, + 'sanitize_title' => true, + 'sanitize_user_field' => true, + 'sanitize_user' => true, + 'validate_file' => true, + 'wp_handle_sideload' => true, + 'wp_handle_upload' => true, + 'wp_kses_allowed_html' => true, + 'wp_kses_data' => true, + 'wp_kses_post' => true, + 'wp_kses' => true, + 'wp_parse_id_list' => true, + 'wp_redirect' => true, + 'wp_safe_redirect' => true, + 'wp_sanitize_redirect' => true, + 'wp_strip_all_tags' => true, + ); + + /** + * Sanitizing functions that implicitly unslash the data passed to them. + * + * This list is complementary to the `$sanitizingFunctions` list. + * Sanitizing functions should be added to this list if they also + * implicitely unslash data and to the `$sanitizingFunctions` list + * if they don't. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $unslashingSanitizingFunctions = array( + 'absint' => true, + 'boolval' => true, + 'count' => true, + 'doubleval' => true, + 'floatval' => true, + 'intval' => true, + 'sanitize_key' => true, + 'sizeof' => true, + ); + + /** + * Functions which unslash the data passed to them. + * + * @since 2.1.0 + * + * @var array + */ + protected $unslashingFunctions = array( + 'stripslashes_deep' => true, + 'stripslashes_from_strings_only' => true, + 'wp_unslash' => true, + ); + + /** + * List of PHP native functions to test the type of a variable. + * + * Using these functions is safe in combination with superglobals without + * unslashing or sanitization. + * + * They should, however, not be regarded as unslashing or sanitization functions. + * + * @since 2.1.0 + * + * @var array + */ + protected $typeTestFunctions = array( + 'is_array' => true, + 'is_bool' => true, + 'is_callable' => true, + 'is_countable' => true, + 'is_double' => true, + 'is_float' => true, + 'is_int' => true, + 'is_integer' => true, + 'is_iterable' => true, + 'is_long' => true, + 'is_null' => true, + 'is_numeric' => true, + 'is_object' => true, + 'is_real' => true, + 'is_resource' => true, + 'is_scalar' => true, + 'is_string' => true, + ); + + /** + * Token which when they preceed code indicate the value is safely casted. + * + * @since 1.1.0 + * + * @var array + */ + protected $safe_casts = array( + \T_INT_CAST => true, + \T_DOUBLE_CAST => true, + \T_BOOL_CAST => true, + \T_UNSET_CAST => true, + ); + + /** + * List of array functions which apply a callback to the array. + * + * These are often used for sanitization/escaping an array variable. + * + * Note: functions which alter the array by reference are not listed here on purpose. + * These cannot easily be used for sanitization as they can't be combined with unslashing. + * Similarly, they cannot be used for late escaping as the return value is a boolean, not + * the altered array. + * + * @since 2.1.0 + * + * @var array => + */ + protected $arrayWalkingFunctions = array( + 'array_map' => 1, + 'map_deep' => 2, + ); + + /** + * Array functions to compare a $needle to a predefined set of values. + * + * If the value is set to an integer, the function needs to have at least that + * many parameters for it to be considered as a comparison. + * + * @since 2.1.0 + * + * @var array => + */ + protected $arrayCompareFunctions = array( + 'in_array' => true, + 'array_search' => true, + 'array_keys' => 2, + ); + + /** + * Functions that format strings. + * + * These functions are often used for formatting values just before output, and + * it is common practice to escape the individual parameters passed to them as + * needed instead of escaping the entire result. This is especially true when the + * string being formatted contains HTML, which makes escaping the full result + * more difficult. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $formattingFunctions = array( + 'array_fill' => true, + 'ent2ncr' => true, + 'implode' => true, + 'join' => true, + 'nl2br' => true, + 'sprintf' => true, + 'vsprintf' => true, + 'wp_sprintf' => true, + ); + + /** + * Functions which print output incorporating the values passed to them. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $printingFunctions = array( + '_deprecated_argument' => true, + '_deprecated_constructor' => true, + '_deprecated_file' => true, + '_deprecated_function' => true, + '_deprecated_hook' => true, + '_doing_it_wrong' => true, + '_e' => true, + '_ex' => true, + 'printf' => true, + 'trigger_error' => true, + 'user_error' => true, + 'vprintf' => true, + 'wp_die' => true, + 'wp_dropdown_pages' => true, + ); + + /** + * Functions that escape values for use in SQL queries. + * + * @since 0.9.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $SQLEscapingFunctions = array( + 'absint' => true, + 'esc_sql' => true, + 'floatval' => true, + 'intval' => true, + 'like_escape' => true, + ); + + /** + * Functions whose output is automatically escaped for use in SQL queries. + * + * @since 0.9.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $SQLAutoEscapedFunctions = array( + 'count' => true, + ); + + /** + * A list of functions that get data from the cache. + * + * @since 0.6.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $cacheGetFunctions = array( + 'wp_cache_get' => true, + ); + + /** + * A list of functions that set data in the cache. + * + * @since 0.6.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $cacheSetFunctions = array( + 'wp_cache_set' => true, + 'wp_cache_add' => true, + ); + + /** + * A list of functions that delete data from the cache. + * + * @since 0.6.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $cacheDeleteFunctions = array( + 'wp_cache_delete' => true, + 'clean_attachment_cache' => true, + 'clean_blog_cache' => true, + 'clean_bookmark_cache' => true, + 'clean_category_cache' => true, + 'clean_comment_cache' => true, + 'clean_network_cache' => true, + 'clean_object_term_cache' => true, + 'clean_page_cache' => true, + 'clean_post_cache' => true, + 'clean_term_cache' => true, + 'clean_user_cache' => true, + ); + + /** + * A list of functions that invoke WP hooks (filters/actions). + * + * @since 0.10.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array + */ + protected $hookInvokeFunctions = array( + 'do_action' => true, + 'do_action_ref_array' => true, + 'do_action_deprecated' => true, + 'apply_filters' => true, + 'apply_filters_ref_array' => true, + 'apply_filters_deprecated' => true, + ); + + /** + * A list of functions that are used to interact with the WP plugins API. + * + * @since 0.10.0 + * @since 0.11.0 Changed from public static to protected non-static. + * + * @var array => + */ + protected $hookFunctions = array( + 'has_filter' => 1, + 'add_filter' => 1, + 'remove_filter' => 1, + 'remove_all_filters' => 1, + 'doing_filter' => 1, // Hook name optional. + 'has_action' => 1, + 'add_action' => 1, + 'doing_action' => 1, // Hook name optional. + 'did_action' => 1, + 'remove_action' => 1, + 'remove_all_actions' => 1, + 'current_filter' => 0, // No hook name argument. + ); + + /** + * List of global WP variables. + * + * @since 0.3.0 + * @since 0.11.0 Changed visibility from public to protected. + * @since 0.12.0 Renamed from `$globals` to `$wp_globals` to be more descriptive. + * @since 0.12.0 Moved here from the WordPress.Variables.GlobalVariables sniff. + * + * @var array + */ + protected $wp_globals = array( + '_links_add_base' => true, + '_links_add_target' => true, + '_menu_item_sort_prop' => true, + '_nav_menu_placeholder' => true, + '_new_bundled_files' => true, + '_old_files' => true, + '_parent_pages' => true, + '_registered_pages' => true, + '_updated_user_settings' => true, + '_wp_additional_image_sizes' => true, + '_wp_admin_css_colors' => true, + '_wp_default_headers' => true, + '_wp_deprecated_widgets_callbacks' => true, + '_wp_last_object_menu' => true, + '_wp_last_utility_menu' => true, + '_wp_menu_nopriv' => true, + '_wp_nav_menu_max_depth' => true, + '_wp_post_type_features' => true, + '_wp_real_parent_file' => true, + '_wp_registered_nav_menus' => true, + '_wp_sidebars_widgets' => true, + '_wp_submenu_nopriv' => true, + '_wp_suspend_cache_invalidation' => true, + '_wp_theme_features' => true, + '_wp_using_ext_object_cache' => true, + 'action' => true, + 'active_signup' => true, + 'admin_body_class' => true, + 'admin_page_hooks' => true, + 'all_links' => true, + 'allowedentitynames' => true, + 'allowedposttags' => true, + 'allowedtags' => true, + 'auth_secure_cookie' => true, + 'authordata' => true, + 'avail_post_mime_types' => true, + 'avail_post_stati' => true, + 'blog_id' => true, + 'blog_title' => true, + 'blogname' => true, + 'cat' => true, + 'cat_id' => true, + 'charset_collate' => true, + 'comment' => true, + 'comment_alt' => true, + 'comment_depth' => true, + 'comment_status' => true, + 'comment_thread_alt' => true, + 'comment_type' => true, + 'comments' => true, + 'compress_css' => true, + 'compress_scripts' => true, + 'concatenate_scripts' => true, + 'content_width' => true, + 'current_blog' => true, + 'current_screen' => true, + 'current_site' => true, + 'current_user' => true, + 'currentcat' => true, + 'currentday' => true, + 'currentmonth' => true, + 'custom_background' => true, + 'custom_image_header' => true, + 'default_menu_order' => true, + 'descriptions' => true, + 'domain' => true, + 'editor_styles' => true, + 'error' => true, + 'errors' => true, + 'EZSQL_ERROR' => true, + 'feeds' => true, + 'GETID3_ERRORARRAY' => true, + 'hook_suffix' => true, + 'HTTP_RAW_POST_DATA' => true, + 'id' => true, + 'in_comment_loop' => true, + 'interim_login' => true, + 'is_apache' => true, + 'is_chrome' => true, + 'is_gecko' => true, + 'is_IE' => true, + 'is_IIS' => true, + 'is_iis7' => true, + 'is_macIE' => true, + 'is_NS4' => true, + 'is_opera' => true, + 'is_safari' => true, + 'is_winIE' => true, + 'l10n' => true, + 'link' => true, + 'link_id' => true, + 'locale' => true, + 'locked_post_status' => true, + 'lost' => true, + 'm' => true, + 'map' => true, + 'menu' => true, + 'menu_order' => true, + 'merged_filters' => true, + 'mode' => true, + 'monthnum' => true, + 'more' => true, + 'mu_plugin' => true, + 'multipage' => true, + 'names' => true, + 'nav_menu_selected_id' => true, + 'network_plugin' => true, + 'new_whitelist_options' => true, + 'numpages' => true, + 'one_theme_location_no_menus' => true, + 'opml' => true, + 'order' => true, + 'orderby' => true, + 'overridden_cpage' => true, + 'page' => true, + 'paged' => true, + 'pagenow' => true, + 'pages' => true, + 'parent_file' => true, + 'pass_allowed_html' => true, + 'pass_allowed_protocols' => true, + 'path' => true, + 'per_page' => true, + 'PHP_SELF' => true, + 'phpmailer' => true, + 'plugin_page' => true, + 'plugin' => true, + 'plugins' => true, + 'post' => true, + 'post_default_category' => true, + 'post_default_title' => true, + 'post_ID' => true, + 'post_id' => true, + 'post_mime_types' => true, + 'post_type' => true, + 'post_type_object' => true, + 'posts' => true, + 'preview' => true, + 'previouscat' => true, + 'previousday' => true, + 'previousweekday' => true, + 'redir_tab' => true, + 'required_mysql_version' => true, + 'required_php_version' => true, + 'rnd_value' => true, + 'role' => true, + 's' => true, + 'search' => true, + 'self' => true, + 'shortcode_tags' => true, + 'show_admin_bar' => true, + 'sidebars_widgets' => true, + 'status' => true, + 'submenu' => true, + 'submenu_file' => true, + 'super_admins' => true, + 'tab' => true, + 'table_prefix' => true, + 'tabs' => true, + 'tag' => true, + 'tag_ID' => true, + 'targets' => true, + 'tax' => true, + 'taxnow' => true, + 'taxonomy' => true, + 'term' => true, + 'text_direction' => true, + 'theme_field_defaults' => true, + 'themes_allowedtags' => true, + 'timeend' => true, + 'timestart' => true, + 'tinymce_version' => true, + 'title' => true, + 'totals' => true, + 'type' => true, + 'typenow' => true, + 'updated_timestamp' => true, + 'upgrading' => true, + 'urls' => true, + 'user_email' => true, + 'user_ID' => true, + 'user_identity' => true, + 'user_level' => true, + 'user_login' => true, + 'user_url' => true, + 'userdata' => true, + 'usersearch' => true, + 'whitelist_options' => true, + 'withcomments' => true, + 'wp' => true, + 'wp_actions' => true, + 'wp_admin_bar' => true, + 'wp_cockneyreplace' => true, + 'wp_current_db_version' => true, + 'wp_current_filter' => true, + 'wp_customize' => true, + 'wp_dashboard_control_callbacks' => true, + 'wp_db_version' => true, + 'wp_did_header' => true, + 'wp_embed' => true, + 'wp_file_descriptions' => true, + 'wp_filesystem' => true, + 'wp_filter' => true, + 'wp_hasher' => true, + 'wp_header_to_desc' => true, + 'wp_importers' => true, + 'wp_json' => true, + 'wp_list_table' => true, + 'wp_local_package' => true, + 'wp_locale' => true, + 'wp_meta_boxes' => true, + 'wp_object_cache' => true, + 'wp_plugin_paths' => true, + 'wp_post_statuses' => true, + 'wp_post_types' => true, + 'wp_queries' => true, + 'wp_query' => true, + 'wp_registered_sidebars' => true, + 'wp_registered_widget_controls' => true, + 'wp_registered_widget_updates' => true, + 'wp_registered_widgets' => true, + 'wp_rewrite' => true, + 'wp_rich_edit' => true, + 'wp_rich_edit_exists' => true, + 'wp_roles' => true, + 'wp_scripts' => true, + 'wp_settings_errors' => true, + 'wp_settings_fields' => true, + 'wp_settings_sections' => true, + 'wp_smiliessearch' => true, + 'wp_styles' => true, + 'wp_taxonomies' => true, + 'wp_the_query' => true, + 'wp_theme_directories' => true, + 'wp_themes' => true, + 'wp_user_roles' => true, + 'wp_version' => true, + 'wp_widget_factory' => true, + 'wp_xmlrpc_server' => true, + 'wpcommentsjavascript' => true, + 'wpcommentspopupfile' => true, + 'wpdb' => true, + 'wpsmiliestrans' => true, + 'year' => true, + ); + + /** + * A list of superglobals that incorporate user input. + * + * @since 0.5.0 + * @since 0.11.0 Changed from static to non-static. + * + * @var string[] + */ + protected $input_superglobals = array( + '$_COOKIE', + '$_GET', + '$_FILES', + '$_POST', + '$_REQUEST', + '$_SERVER', + ); + + /** + * Whitelist of classes which test classes can extend. + * + * @since 0.11.0 + * + * @var string[] + */ + protected $test_class_whitelist = array( + 'WP_UnitTestCase_Base' => true, + 'WP_UnitTestCase' => true, + 'WP_Ajax_UnitTestCase' => true, + 'WP_Canonical_UnitTestCase' => true, + 'WP_Test_REST_TestCase' => true, + 'WP_Test_REST_Controller_Testcase' => true, + 'WP_Test_REST_Post_Type_Controller_Testcase' => true, + 'WP_XMLRPC_UnitTestCase' => true, + 'PHPUnit_Framework_TestCase' => true, + 'PHPUnit\Framework\TestCase' => true, + // PHPUnit native TestCase class when imported via use statement. + 'TestCase' => true, + ); + + /** + * The current file being sniffed. + * + * @since 0.4.0 + * + * @var \PHP_CodeSniffer\Files\File + */ + protected $phpcsFile; + + /** + * The list of tokens in the current file being sniffed. + * + * @since 0.4.0 + * + * @var array + */ + protected $tokens; + + /** + * Set sniff properties and hand off to child class for processing of the token. + * + * @since 0.11.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process( File $phpcsFile, $stackPtr ) { + $this->init( $phpcsFile ); + return $this->process_token( $stackPtr ); + } + + /** + * Processes a sniff when one of its tokens is encountered. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + abstract public function process_token( $stackPtr ); + + /** + * Initialize the class for the current process. + * + * This method must be called by child classes before using many of the methods + * below. + * + * @since 0.4.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file currently being processed. + */ + protected function init( File $phpcsFile ) { + $this->phpcsFile = $phpcsFile; + $this->tokens = $phpcsFile->getTokens(); + } + + /** + * Strip quotes surrounding an arbitrary string. + * + * Intended for use with the contents of a T_CONSTANT_ENCAPSED_STRING / T_DOUBLE_QUOTED_STRING. + * + * @since 0.11.0 + * + * @param string $string The raw string. + * @return string String without quotes around it. + */ + public function strip_quotes( $string ) { + return preg_replace( '`^([\'"])(.*)\1$`Ds', '$2', $string ); + } + + /** + * Add a PHPCS message to the output stack as either a warning or an error. + * + * @since 0.11.0 + * + * @param string $message The message. + * @param int $stackPtr The position of the token the message relates to. + * @param bool $is_error Optional. Whether to report the message as an 'error' or 'warning'. + * Defaults to true (error). + * @param string $code Optional error code for the message. Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * @param int $severity Optional. Severity level. Defaults to 0 which will translate to + * the PHPCS default severity level. + * @return bool + */ + protected function addMessage( $message, $stackPtr, $is_error = true, $code = 'Found', $data = array(), $severity = 0 ) { + return $this->throwMessage( $message, $stackPtr, $is_error, $code, $data, $severity, false ); + } + + /** + * Add a fixable PHPCS message to the output stack as either a warning or an error. + * + * @since 0.11.0 + * + * @param string $message The message. + * @param int $stackPtr The position of the token the message relates to. + * @param bool $is_error Optional. Whether to report the message as an 'error' or 'warning'. + * Defaults to true (error). + * @param string $code Optional error code for the message. Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * @param int $severity Optional. Severity level. Defaults to 0 which will translate to + * the PHPCS default severity level. + * @return bool + */ + protected function addFixableMessage( $message, $stackPtr, $is_error = true, $code = 'Found', $data = array(), $severity = 0 ) { + return $this->throwMessage( $message, $stackPtr, $is_error, $code, $data, $severity, true ); + } + + /** + * Add a PHPCS message to the output stack as either a warning or an error. + * + * @since 0.11.0 + * + * @param string $message The message. + * @param int $stackPtr The position of the token the message relates to. + * @param bool $is_error Optional. Whether to report the message as an 'error' or 'warning'. + * Defaults to true (error). + * @param string $code Optional error code for the message. Defaults to 'Found'. + * @param array $data Optional input for the data replacements. + * @param int $severity Optional. Severity level. Defaults to 0 which will translate to + * the PHPCS default severity level. + * @param bool $fixable Optional. Whether this is a fixable error. Defaults to false. + * @return bool + */ + private function throwMessage( $message, $stackPtr, $is_error = true, $code = 'Found', $data = array(), $severity = 0, $fixable = false ) { + + $method = 'add'; + if ( true === $fixable ) { + $method .= 'Fixable'; + } + + if ( true === $is_error ) { + $method .= 'Error'; + } else { + $method .= 'Warning'; + } + + return \call_user_func( array( $this->phpcsFile, $method ), $message, $stackPtr, $code, $data, $severity ); + } + + /** + * Convert an arbitrary string to an alphanumeric string with underscores. + * + * Pre-empt issues with arbitrary strings being used as error codes in XML and PHP. + * + * @since 0.11.0 + * + * @param string $base_string Arbitrary string. + * + * @return string + */ + protected function string_to_errorcode( $base_string ) { + return preg_replace( '`[^a-z0-9_]`i', '_', $base_string ); + } + + /** + * Transform the name of a PHP construct (function, variable etc) to one in snake_case. + * + * @since 2.0.0 Moved from the `WordPress.NamingConventions.ValidFunctionName` sniff + * to this class, renamed from `get_name_suggestion` and made static + * so it can also be used by classes which don't extend this class. + * + * @param string $name The construct name. + * + * @return string + */ + public static function get_snake_case_name_suggestion( $name ) { + $suggested = preg_replace( '`([A-Z])`', '_$1', $name ); + $suggested = strtolower( $suggested ); + $suggested = str_replace( '__', '_', $suggested ); + $suggested = trim( $suggested, '_' ); + return $suggested; + } + + /** + * Merge a pre-set array with a ruleset provided array. + * + * - By default flips custom lists to allow for using `isset()` instead + * of `in_array()`. + * - When `$flip` is true: + * * Presumes the base array is in a `'value' => true` format. + * * Any custom items will be given the value `false` to be able to + * distinguish them from pre-set (base array) values. + * * Will filter previously added custom items out from the base array + * before merging/returning to allow for resetting to the base array. + * + * {@internal Function is static as it doesn't use any of the properties or others + * methods anyway and this way the `WordPress.NamingConventions.ValidVariableName` sniff + * which extends an upstream sniff can also use it.}} + * + * @since 0.11.0 + * @since 2.0.0 No longer supports custom array properties which were incorrectly + * passed as a string. + * + * @param array $custom Custom list as provided via a ruleset. + * @param array $base Optional. Base list. Defaults to an empty array. + * Expects `value => true` format when `$flip` is true. + * @param bool $flip Optional. Whether or not to flip the custom list. + * Defaults to true. + * @return array + */ + public static function merge_custom_array( $custom, $base = array(), $flip = true ) { + if ( true === $flip ) { + $base = array_filter( $base ); + } + + if ( empty( $custom ) || ! \is_array( $custom ) ) { + return $base; + } + + if ( true === $flip ) { + $custom = array_fill_keys( $custom, false ); + } + + if ( empty( $base ) ) { + return $custom; + } + + return array_merge( $base, $custom ); + } + + /** + * Get the last pointer in a line. + * + * @since 0.4.0 + * + * @param integer $stackPtr The position of the current token in the stack passed + * in $tokens. + * + * @return integer Position of the last pointer on that line. + */ + protected function get_last_ptr_on_line( $stackPtr ) { + + $tokens = $this->tokens; + $currentLine = $tokens[ $stackPtr ]['line']; + $nextPtr = ( $stackPtr + 1 ); + + while ( isset( $tokens[ $nextPtr ] ) && $tokens[ $nextPtr ]['line'] === $currentLine ) { + $nextPtr++; + // Do nothing, we just want the last token of the line. + } + + // We've made it to the next line, back up one to the last in the previous line. + // We do this for micro-optimization of the above loop. + $lastPtr = ( $nextPtr - 1 ); + + return $lastPtr; + } + + /** + * Overrule the minimum supported WordPress version with a command-line/config value. + * + * Handle setting the minimum supported WP version in one go for all sniffs which + * expect it via the command line or via a `` variable in a ruleset. + * The config variable overrules the default `$minimum_supported_version` and/or a + * `$minimum_supported_version` set for individual sniffs through the ruleset. + * + * @since 0.14.0 + */ + protected function get_wp_version_from_cl() { + $cl_supported_version = trim( PHPCSHelper::get_config_data( 'minimum_supported_wp_version' ) ); + if ( ! empty( $cl_supported_version ) + && filter_var( $cl_supported_version, \FILTER_VALIDATE_FLOAT ) !== false + ) { + $this->minimum_supported_version = $cl_supported_version; + } + } + + /** + * Find whitelisting comment. + * + * Comment must be at the end of the line or at the end of the statement + * and must use // format. + * It can be prefixed or suffixed with anything e.g. "foobar" will match: + * ... // foobar okay + * ... // WPCS: foobar whitelist. + * + * There is an exception, and that is when PHP is being interspersed with HTML. + * In that case, the comment should always come at the end of the statement (right + * before the closing tag, ?>). For example: + * + * + * + * @since 0.4.0 + * @since 0.14.0 Whitelist comments at the end of the statement are now also accepted. + * + * @deprecated 2.0.0 Use the PHPCS native `phpcs:ignore` annotations instead. + * + * @param string $comment Comment to find. + * @param integer $stackPtr The position of the current token in the stack passed + * in $tokens. + * + * @return boolean True if whitelisting comment was found, false otherwise. + */ + protected function has_whitelist_comment( $comment, $stackPtr ) { + + // Respect the PHPCS 3.x --ignore-annotations setting. + if ( true === PHPCSHelper::ignore_annotations( $this->phpcsFile ) ) { + return false; + } + + static $thrown_notices = array(); + + $deprecation_notice = 'Using the WPCS native whitelist comments is deprecated. Please use the PHPCS native "phpcs:ignore Standard.Category.SniffName.ErrorCode" annotations instead. Found: %s'; + $deprecation_code = 'DeprecatedWhitelistCommentFound'; + $filename = $this->phpcsFile->getFileName(); + + $regex = '#\b' . preg_quote( $comment, '#' ) . '\b#i'; + + // There is a findEndOfStatement() method, but it considers more tokens than + // we need to consider here. + $end_of_statement = $this->phpcsFile->findNext( array( \T_CLOSE_TAG, \T_SEMICOLON ), $stackPtr ); + + if ( false !== $end_of_statement ) { + // If the statement was ended by a semicolon, check if there is a whitelist comment directly after it. + if ( \T_SEMICOLON === $this->tokens[ $end_of_statement ]['code'] ) { + $lastPtr = $this->phpcsFile->findNext( \T_WHITESPACE, ( $end_of_statement + 1 ), null, true ); + } elseif ( \T_CLOSE_TAG === $this->tokens[ $end_of_statement ]['code'] ) { + // If the semicolon was left out and it was terminated by an ending tag, we need to look backwards. + $lastPtr = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $end_of_statement - 1 ), null, true ); + } + + if ( ( \T_COMMENT === $this->tokens[ $lastPtr ]['code'] + || ( isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) + && \T_PHPCS_SET !== $this->tokens[ $lastPtr ]['code'] ) ) + && $this->tokens[ $lastPtr ]['line'] === $this->tokens[ $end_of_statement ]['line'] + && preg_match( $regex, $this->tokens[ $lastPtr ]['content'] ) === 1 + ) { + if ( isset( $thrown_notices[ $filename ][ $lastPtr ] ) === false + && isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) === false + ) { + $this->phpcsFile->addWarning( + $deprecation_notice, + $lastPtr, + $deprecation_code, + array( $this->tokens[ $lastPtr ]['content'] ) + ); + + $thrown_notices[ $filename ][ $lastPtr ] = true; + } + + return true; + } + } + + // No whitelist comment found so far. Check at the end of the stackPtr line. + // Note: a T_COMMENT includes the new line character, so may be the last token on the line! + $end_of_line = $this->get_last_ptr_on_line( $stackPtr ); + $lastPtr = $this->phpcsFile->findPrevious( \T_WHITESPACE, $end_of_line, null, true ); + + if ( ( \T_COMMENT === $this->tokens[ $lastPtr ]['code'] + || ( isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) + && \T_PHPCS_SET !== $this->tokens[ $lastPtr ]['code'] ) ) + && $this->tokens[ $lastPtr ]['line'] === $this->tokens[ $stackPtr ]['line'] + && preg_match( $regex, $this->tokens[ $lastPtr ]['content'] ) === 1 + ) { + if ( isset( $thrown_notices[ $filename ][ $lastPtr ] ) === false + && isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastPtr ]['code'] ] ) === false + ) { + $this->phpcsFile->addWarning( + $deprecation_notice, + $lastPtr, + $deprecation_code, + array( $this->tokens[ $lastPtr ]['content'] ) + ); + + $thrown_notices[ $filename ][ $lastPtr ] = true; + } + + return true; + } + + return false; + } + + /** + * Check if a token is used within a unit test. + * + * Unit test methods are identified as such: + * - Method is within a known unit test class; + * - or Method is within a class/trait which extends a known unit test class. + * + * @since 0.11.0 + * @since 1.1.0 Supports anonymous test classes and improved handling of nested scopes. + * + * @param int $stackPtr The position of the token to be examined. + * + * @return bool True if the token is within a unit test, false otherwise. + */ + protected function is_token_in_test_method( $stackPtr ) { + // Is the token inside of a function definition ? + $functionToken = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + if ( false === $functionToken ) { + // No conditions or no function condition. + return false; + } + + $conditions = $this->tokens[ $stackPtr ]['conditions']; + foreach ( $conditions as $token => $condition ) { + if ( $token === $functionToken ) { + // Only examine the conditions the function is nested in, not those nested within the function. + break; + } + + if ( isset( Tokens::$ooScopeTokens[ $condition ] ) ) { + $is_test_class = $this->is_test_class( $token ); + if ( true === $is_test_class ) { + return true; + } + } + } + + return false; + } + + /** + * Check if a class token is part of a unit test suite. + * + * Unit test classes are identified as such: + * - Class which either extends WP_UnitTestCase or PHPUnit_Framework_TestCase + * or a custom whitelisted unit test class. + * + * @since 0.12.0 Split off from the `is_token_in_test_method()` method. + * @since 1.0.0 Improved recognition of namespaced class names. + * + * @param int $stackPtr The position of the token to be examined. + * This should be a class, anonymous class or trait token. + * + * @return bool True if the class is a unit test class, false otherwise. + */ + protected function is_test_class( $stackPtr ) { + + if ( isset( $this->tokens[ $stackPtr ], Tokens::$ooScopeTokens[ $this->tokens[ $stackPtr ]['code'] ] ) === false ) { + return false; + } + + // Add any potentially whitelisted custom test classes to the whitelist. + $whitelist = $this->merge_custom_array( + $this->custom_test_class_whitelist, + $this->test_class_whitelist + ); + + /* + * Show some tolerance for user input. + * The custom test class names should be passed as FQN without a prefixing `\`. + */ + foreach ( $whitelist as $k => $v ) { + $whitelist[ $k ] = ltrim( $v, '\\' ); + } + + // Is the class/trait one of the whitelisted test classes ? + $namespace = $this->determine_namespace( $stackPtr ); + $className = $this->phpcsFile->getDeclarationName( $stackPtr ); + if ( '' !== $namespace ) { + if ( isset( $whitelist[ $namespace . '\\' . $className ] ) ) { + return true; + } + } elseif ( isset( $whitelist[ $className ] ) ) { + return true; + } + + // Does the class/trait extend one of the whitelisted test classes ? + $extendedClassName = $this->phpcsFile->findExtendedClassName( $stackPtr ); + if ( false === $extendedClassName ) { + return false; + } + + if ( '\\' === $extendedClassName[0] ) { + if ( isset( $whitelist[ substr( $extendedClassName, 1 ) ] ) ) { + return true; + } + } elseif ( '' !== $namespace ) { + if ( isset( $whitelist[ $namespace . '\\' . $extendedClassName ] ) ) { + return true; + } + } elseif ( isset( $whitelist[ $extendedClassName ] ) ) { + return true; + } + + /* + * Not examining imported classes via `use` statements as with the variety of syntaxes, + * this would get very complicated. + * After all, users can add an `` for a particular sniff to their + * custom ruleset to selectively exclude the test directory. + */ + + return false; + } + + /** + * Check if this variable is being assigned a value. + * + * E.g., $var = 'foo'; + * + * Also handles array assignments to arbitrary depth: + * + * $array['key'][ $foo ][ something() ] = $bar; + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. This must point to + * either a T_VARIABLE or T_CLOSE_SQUARE_BRACKET token. + * + * @return bool Whether the token is a variable being assigned a value. + */ + protected function is_assignment( $stackPtr ) { + + static $valid = array( + \T_VARIABLE => true, + \T_CLOSE_SQUARE_BRACKET => true, + ); + + // Must be a variable, constant or closing square bracket (see below). + if ( ! isset( $valid[ $this->tokens[ $stackPtr ]['code'] ] ) ) { + return false; + } + + $next_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $stackPtr + 1 ), + null, + true, + null, + true + ); + + // No token found. + if ( false === $next_non_empty ) { + return false; + } + + // If the next token is an assignment, that's all we need to know. + if ( isset( Tokens::$assignmentTokens[ $this->tokens[ $next_non_empty ]['code'] ] ) ) { + return true; + } + + // Check if this is an array assignment, e.g., `$var['key'] = 'val';` . + if ( \T_OPEN_SQUARE_BRACKET === $this->tokens[ $next_non_empty ]['code'] + && isset( $this->tokens[ $next_non_empty ]['bracket_closer'] ) + ) { + return $this->is_assignment( $this->tokens[ $next_non_empty ]['bracket_closer'] ); + } + + return false; + } + + /** + * Check if this token has an associated nonce check. + * + * @since 0.5.0 + * + * @param int $stackPtr The position of the current token in the stack of tokens. + * + * @return bool + */ + protected function has_nonce_check( $stackPtr ) { + + /** + * A cache of the scope that we last checked for nonce verification in. + * + * @var array { + * @var string $file The name of the file. + * @var int $start The index of the token where the scope started. + * @var int $end The index of the token where the scope ended. + * @var bool|int $nonce_check The index of the token where an nonce check + * was found, or false if none was found. + * } + */ + static $last; + + $start = 0; + $end = $stackPtr; + + $tokens = $this->phpcsFile->getTokens(); + + // If we're in a function, only look inside of it. + // Once PHPCS 3.5.0 comes out this should be changed to the new Conditions::GetLastCondition() method. + if ( isset( $tokens[ $stackPtr ]['conditions'] ) === true ) { + $conditions = $tokens[ $stackPtr ]['conditions']; + $conditions = array_reverse( $conditions, true ); + foreach ( $conditions as $tokenPtr => $condition ) { + if ( \T_FUNCTION === $condition || \T_CLOSURE === $condition ) { + $start = $tokens[ $tokenPtr ]['scope_opener']; + break; + } + } + } + + $allow_nonce_after = false; + if ( $this->is_in_isset_or_empty( $stackPtr ) + || $this->is_in_type_test( $stackPtr ) + || $this->is_comparison( $stackPtr ) + || $this->is_in_array_comparison( $stackPtr ) + || $this->is_in_function_call( $stackPtr, $this->unslashingFunctions ) !== false + || $this->is_only_sanitized( $stackPtr ) + ) { + $allow_nonce_after = true; + } + + // We allow for certain actions, such as an isset() check to come before the nonce check. + // If this superglobal is inside such a check, look for the nonce after it as well, + // all the way to the end of the scope. + if ( true === $allow_nonce_after ) { + $end = ( 0 === $start ) ? $this->phpcsFile->numTokens : $tokens[ $start ]['scope_closer']; + } + + // Check if we've looked here before. + $filename = $this->phpcsFile->getFilename(); + + if ( is_array( $last ) + && $filename === $last['file'] + && $start === $last['start'] + ) { + + if ( false !== $last['nonce_check'] ) { + // If we have already found an nonce check in this scope, we just + // need to check whether it comes before this token. It is OK if the + // check is after the token though, if this was only a isset() check. + return ( true === $allow_nonce_after || $last['nonce_check'] < $stackPtr ); + } elseif ( $end <= $last['end'] ) { + // If not, we can still go ahead and return false if we've already + // checked to the end of the search area. + return false; + } + + // We haven't checked this far yet, but we can still save work by + // skipping over the part we've already checked. + $start = $last['end']; + } else { + $last = array( + 'file' => $filename, + 'start' => $start, + 'end' => $end, + ); + } + + // Loop through the tokens looking for nonce verification functions. + for ( $i = $start; $i < $end; $i++ ) { + // Skip over nested closed scope constructs. + if ( \T_FUNCTION === $tokens[ $i ]['code'] + || \T_CLOSURE === $tokens[ $i ]['code'] + || isset( Tokens::$ooScopeTokens[ $tokens[ $i ]['code'] ] ) + ) { + if ( isset( $tokens[ $i ]['scope_closer'] ) ) { + $i = $tokens[ $i ]['scope_closer']; + } + continue; + } + + // If this isn't a function name, skip it. + if ( \T_STRING !== $tokens[ $i ]['code'] ) { + continue; + } + + // If this is one of the nonce verification functions, we can bail out. + if ( isset( $this->nonceVerificationFunctions[ $tokens[ $i ]['content'] ] ) ) { + /* + * Now, make sure it is a call to a global function. + */ + if ( $this->is_class_object_call( $i ) === true ) { + continue; + } + + if ( $this->is_token_namespaced( $i ) === true ) { + continue; + } + + $last['nonce_check'] = $i; + return true; + } + } + + // We're still here, so no luck. + $last['nonce_check'] = false; + + return false; + } + + /** + * Check if a token is inside of an isset(), empty() or array_key_exists() statement. + * + * @since 0.5.0 + * @since 2.1.0 Now checks for the token being used as the array parameter + * in function calls to array_key_exists() and key_exists() as well. + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is inside an isset() or empty() statement. + */ + protected function is_in_isset_or_empty( $stackPtr ) { + + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return false; + } + + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + + end( $nested_parenthesis ); + $open_parenthesis = key( $nested_parenthesis ); + + $previous_non_empty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $open_parenthesis - 1 ), null, true, null, true ); + if ( false === $previous_non_empty ) { + return false; + } + + $previous_code = $this->tokens[ $previous_non_empty ]['code']; + if ( \T_ISSET === $previous_code || \T_EMPTY === $previous_code ) { + return true; + } + + $valid_functions = array( + 'array_key_exists' => true, + 'key_exists' => true, // Alias. + ); + + $functionPtr = $this->is_in_function_call( $stackPtr, $valid_functions ); + if ( false !== $functionPtr ) { + $second_param = $this->get_function_call_parameter( $functionPtr, 2 ); + if ( $stackPtr >= $second_param['start'] && $stackPtr <= $second_param['end'] ) { + return true; + } + } + + return false; + } + + /** + * Check if a particular token is a (static or non-static) call to a class method or property. + * + * @internal Note: this may still mistake a namespaced function imported via a `use` statement for + * a global function! + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool + */ + protected function is_class_object_call( $stackPtr ) { + $before = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true, null, true ); + + if ( false === $before ) { + return false; + } + + if ( \T_OBJECT_OPERATOR !== $this->tokens[ $before ]['code'] + && \T_DOUBLE_COLON !== $this->tokens[ $before ]['code'] + ) { + return false; + } + + return true; + } + + /** + * Check if a particular token is prefixed with a namespace. + * + * @internal This will give a false positive if the file is not namespaced and the token is prefixed + * with `namespace\`. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool + */ + protected function is_token_namespaced( $stackPtr ) { + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true, null, true ); + + if ( false === $prev ) { + return false; + } + + if ( \T_NS_SEPARATOR !== $this->tokens[ $prev ]['code'] ) { + return false; + } + + $before_prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $prev - 1 ), null, true, null, true ); + if ( false === $before_prev ) { + return false; + } + + if ( \T_STRING !== $this->tokens[ $before_prev ]['code'] + && \T_NAMESPACE !== $this->tokens[ $before_prev ]['code'] + ) { + return false; + } + + return true; + } + + /** + * Check if a token is (part of) a parameter for a function call to a select list of functions. + * + * This is useful, for instance, when trying to determine the context a variable is used in. + * + * For example: this function could be used to determine if the variable `$foo` is used + * in a global function call to the function `is_foo()`. + * In that case, a call to this function would return the stackPtr to the T_STRING `is_foo` + * for code like: `is_foo( $foo, 'some_other_param' )`, while it would return `false` for + * the following code `is_bar( $foo, 'some_other_param' )`. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * @param array $valid_functions List of valid function names. + * Note: The keys to this array should be the function names + * in lowercase. Values are irrelevant. + * @param bool $global Optional. Whether to make sure that the function call is + * to a global function. If `false`, calls to methods, be it static + * `Class::method()` or via an object `$obj->method()`, and + * namespaced function calls, like `MyNS\function_name()` will + * also be accepted. + * Defaults to `true`. + * @param bool $allow_nested Optional. Whether to allow for nested function calls within the + * call to this function. + * I.e. when checking whether a token is within a function call + * to `strtolower()`, whether to accept `strtolower( trim( $var ) )` + * or only `strtolower( $var )`. + * Defaults to `false`. + * + * @return int|bool Stack pointer to the function call T_STRING token or false otherwise. + */ + protected function is_in_function_call( $stackPtr, $valid_functions, $global = true, $allow_nested = false ) { + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return false; + } + + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + if ( false === $allow_nested ) { + $nested_parenthesis = array_reverse( $nested_parenthesis, true ); + } + + foreach ( $nested_parenthesis as $open => $close ) { + + $prev_non_empty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $open - 1 ), null, true, null, true ); + if ( false === $prev_non_empty || \T_STRING !== $this->tokens[ $prev_non_empty ]['code'] ) { + continue; + } + + if ( isset( $valid_functions[ strtolower( $this->tokens[ $prev_non_empty ]['content'] ) ] ) === false ) { + if ( false === $allow_nested ) { + // Function call encountered, but not to one of the allowed functions. + return false; + } + + continue; + } + + if ( false === $global ) { + return $prev_non_empty; + } + + /* + * Now, make sure it is a global function. + */ + if ( $this->is_class_object_call( $prev_non_empty ) === true ) { + continue; + } + + if ( $this->is_token_namespaced( $prev_non_empty ) === true ) { + continue; + } + + return $prev_non_empty; + } + + return false; + } + + /** + * Check if a token is inside of an is_...() statement. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is being type tested. + */ + protected function is_in_type_test( $stackPtr ) { + /* + * Casting the potential integer stack pointer return value to boolean here is fine. + * The return can never be `0` as there will always be a PHP open tag before the + * function call. + */ + return (bool) $this->is_in_function_call( $stackPtr, $this->typeTestFunctions ); + } + + /** + * Check if something is only being sanitized. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is only within a sanitization. + */ + protected function is_only_sanitized( $stackPtr ) { + + // If it isn't being sanitized at all. + if ( ! $this->is_sanitized( $stackPtr ) ) { + return false; + } + + // If this isn't set, we know the value must have only been casted, because + // is_sanitized() would have returned false otherwise. + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return true; + } + + // At this point we're expecting the value to have not been casted. If it + // was, it wasn't *only* casted, because it's also in a function. + if ( $this->is_safe_casted( $stackPtr ) ) { + return false; + } + + // The only parentheses should belong to the sanitizing function. If there's + // more than one set, this isn't *only* sanitization. + return ( \count( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) === 1 ); + } + + /** + * Check if something is being casted to a safe value. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token being casted. + */ + protected function is_safe_casted( $stackPtr ) { + + // Get the last non-empty token. + $prev = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false === $prev ) { + return false; + } + + // Check if it is a safe cast. + return isset( $this->safe_casts[ $this->tokens[ $prev ]['code'] ] ); + } + + /** + * Check if something is being sanitized. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + * @param bool $require_unslash Whether to give an error if no unslashing function + * is used on the variable before sanitization. + * + * @return bool Whether the token being sanitized. + */ + protected function is_sanitized( $stackPtr, $require_unslash = false ) { + + // First we check if it is being casted to a safe value. + if ( $this->is_safe_casted( $stackPtr ) ) { + return true; + } + + // If this isn't within a function call, we know already that it's not safe. + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + if ( $require_unslash ) { + $this->add_unslash_error( $stackPtr ); + } + + return false; + } + + // Get the function that it's in. + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $nested_openers = array_keys( $nested_parenthesis ); + $function_opener = array_pop( $nested_openers ); + $functionPtr = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $function_opener - 1 ), null, true, null, true ); + + // If it is just being unset, the value isn't used at all, so it's safe. + if ( \T_UNSET === $this->tokens[ $functionPtr ]['code'] ) { + return true; + } + + $valid_functions = $this->sanitizingFunctions; + $valid_functions += $this->unslashingSanitizingFunctions; + $valid_functions += $this->unslashingFunctions; + $valid_functions += $this->arrayWalkingFunctions; + + $functionPtr = $this->is_in_function_call( $stackPtr, $valid_functions ); + + // If this isn't a call to one of the valid functions, it sure isn't a sanitizing function. + if ( false === $functionPtr ) { + if ( true === $require_unslash ) { + $this->add_unslash_error( $stackPtr ); + } + + return false; + } + + $functionName = $this->tokens[ $functionPtr ]['content']; + + // Check if an unslashing function is being used. + if ( isset( $this->unslashingFunctions[ $functionName ] ) ) { + + $is_unslashed = true; + + // Remove the unslashing functions. + $valid_functions = array_diff_key( $valid_functions, $this->unslashingFunctions ); + + // Check is any of the remaining (sanitizing) functions is used. + $higherFunctionPtr = $this->is_in_function_call( $functionPtr, $valid_functions ); + + // If there is no other valid function being used, this value is unsanitized. + if ( false === $higherFunctionPtr ) { + return false; + } + + $functionPtr = $higherFunctionPtr; + $functionName = $this->tokens[ $functionPtr ]['content']; + + } else { + $is_unslashed = false; + } + + // Arrays might be sanitized via an array walking function using a callback. + if ( isset( $this->arrayWalkingFunctions[ $functionName ] ) ) { + + // Get the callback parameter. + $callback = $this->get_function_call_parameter( $functionPtr, $this->arrayWalkingFunctions[ $functionName ] ); + + if ( ! empty( $callback ) ) { + /* + * If this is a function callback (not a method callback array) and we're able + * to resolve the function name, do so. + */ + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $callback['start'], + ( $callback['end'] + 1 ), + true + ); + + if ( false !== $first_non_empty && \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $first_non_empty ]['code'] ) { + $functionName = $this->strip_quotes( $this->tokens[ $first_non_empty ]['content'] ); + } + } + } + + // If slashing is required, give an error. + if ( ! $is_unslashed && $require_unslash && ! isset( $this->unslashingSanitizingFunctions[ $functionName ] ) ) { + $this->add_unslash_error( $stackPtr ); + } + + // Check if this is a sanitizing function. + if ( isset( $this->sanitizingFunctions[ $functionName ] ) || isset( $this->unslashingSanitizingFunctions[ $functionName ] ) ) { + return true; + } + + return false; + } + + /** + * Add an error for missing use of unslashing. + * + * @since 0.5.0 + * + * @param int $stackPtr The index of the token in the stack. + */ + public function add_unslash_error( $stackPtr ) { + + $this->phpcsFile->addError( + '%s data not unslashed before sanitization. Use wp_unslash() or similar', + $stackPtr, + 'MissingUnslash', + array( $this->tokens[ $stackPtr ]['content'] ) + ); + } + + /** + * Get the index keys of an array variable. + * + * E.g., "bar" and "baz" in $foo['bar']['baz']. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the variable token in the stack. + * @param bool $all Whether to get all keys or only the first. + * Defaults to `true`(= all). + * + * @return array An array of index keys whose value is being accessed. + * or an empty array if this is not array access. + */ + protected function get_array_access_keys( $stackPtr, $all = true ) { + + $keys = array(); + + if ( \T_VARIABLE !== $this->tokens[ $stackPtr ]['code'] ) { + return $keys; + } + + $current = $stackPtr; + + do { + // Find the next non-empty token. + $open_bracket = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $current + 1 ), + null, + true + ); + + // If it isn't a bracket, this isn't an array-access. + if ( false === $open_bracket + || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $open_bracket ]['code'] + || ! isset( $this->tokens[ $open_bracket ]['bracket_closer'] ) + ) { + break; + } + + $key = $this->phpcsFile->getTokensAsString( + ( $open_bracket + 1 ), + ( $this->tokens[ $open_bracket ]['bracket_closer'] - $open_bracket - 1 ) + ); + + $keys[] = trim( $key ); + $current = $this->tokens[ $open_bracket ]['bracket_closer']; + } while ( isset( $this->tokens[ $current ] ) && true === $all ); + + return $keys; + } + + /** + * Get the index key of an array variable. + * + * E.g., "bar" in $foo['bar']. + * + * @since 0.5.0 + * @since 2.1.0 Now uses get_array_access_keys() under the hood. + * + * @param int $stackPtr The index of the token in the stack. + * + * @return string|false The array index key whose value is being accessed. + */ + protected function get_array_access_key( $stackPtr ) { + + $keys = $this->get_array_access_keys( $stackPtr, false ); + + if ( isset( $keys[0] ) ) { + return $keys[0]; + } + + return false; + } + + /** + * Check if the existence of a variable is validated with isset(), empty(), array_key_exists() + * or key_exists(). + * + * When $in_condition_only is false, (which is the default), this is considered + * valid: + * + * ```php + * if ( isset( $var ) ) { + * // Do stuff, like maybe return or exit (but could be anything) + * } + * + * foo( $var ); + * ``` + * + * When it is true, that would be invalid, the use of the variable must be within + * the scope of the validating condition, like this: + * + * ```php + * if ( isset( $var ) ) { + * foo( $var ); + * } + * ``` + * + * @since 0.5.0 + * @since 2.1.0 Now recognizes array_key_exists() and key_exists() as validation functions. + * @since 2.1.0 Stricter check on whether the correct variable and the correct + * array keys are being validated. + * + * @param int $stackPtr The index of this token in the stack. + * @param array|string $array_keys An array key to check for ("bar" in $foo['bar']) + * or an array of keys for multi-level array access. + * @param bool $in_condition_only Whether to require that this use of the + * variable occur within the scope of the + * validating condition, or just in the same + * scope as it (default). + * + * @return bool Whether the var is validated. + */ + protected function is_validated( $stackPtr, $array_keys = array(), $in_condition_only = false ) { + + if ( $in_condition_only ) { + /* + * This is a stricter check, requiring the variable to be used only + * within the validation condition. + */ + + // If there are no conditions, there's no validation. + if ( empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + return false; + } + + $conditions = $this->tokens[ $stackPtr ]['conditions']; + end( $conditions ); // Get closest condition. + $conditionPtr = key( $conditions ); + $condition = $this->tokens[ $conditionPtr ]; + + if ( ! isset( $condition['parenthesis_opener'] ) ) { + // Live coding or parse error. + return false; + } + + $scope_start = $condition['parenthesis_opener']; + $scope_end = $condition['parenthesis_closer']; + + } else { + /* + * We are are more loose, requiring only that the variable be validated + * in the same function/file scope as it is used. + */ + + $scope_start = 0; + + // Check if we are in a function. + $function = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + + // If so, we check only within the function, otherwise the whole file. + if ( false !== $function ) { + $scope_start = $this->tokens[ $function ]['scope_opener']; + } else { + // Check if we are in a closure. + $closure = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + + // If so, we check only within the closure. + if ( false !== $closure ) { + $scope_start = $this->tokens[ $closure ]['scope_opener']; + } + } + + $scope_end = $stackPtr; + } + + if ( ! empty( $array_keys ) && ! is_array( $array_keys ) ) { + $array_keys = (array) $array_keys; + } + + $bare_array_keys = array_map( array( $this, 'strip_quotes' ), $array_keys ); + $targets = array( + \T_ISSET => 'construct', + \T_EMPTY => 'construct', + \T_UNSET => 'construct', + \T_STRING => 'function_call', + \T_COALESCE => 'coalesce', + \T_COALESCE_EQUAL => 'coalesce', + ); + + // phpcs:ignore Generic.CodeAnalysis.JumbledIncrementer.Found -- On purpose, see below. + for ( $i = ( $scope_start + 1 ); $i < $scope_end; $i++ ) { + + if ( isset( $targets[ $this->tokens[ $i ]['code'] ] ) === false ) { + continue; + } + + switch ( $targets[ $this->tokens[ $i ]['code'] ] ) { + case 'construct': + $issetOpener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true, null, true ); + if ( false === $issetOpener || \T_OPEN_PARENTHESIS !== $this->tokens[ $issetOpener ]['code'] ) { + // Parse error or live coding. + continue 2; + } + + $issetCloser = $this->tokens[ $issetOpener ]['parenthesis_closer']; + + // Look for this variable. We purposely stomp $i from the parent loop. + for ( $i = ( $issetOpener + 1 ); $i < $issetCloser; $i++ ) { + + if ( \T_VARIABLE !== $this->tokens[ $i ]['code'] ) { + continue; + } + + if ( $this->tokens[ $stackPtr ]['content'] !== $this->tokens[ $i ]['content'] ) { + continue; + } + + // If we're checking for specific array keys (ex: 'hello' in + // $_POST['hello']), that must match too. Quote-style, however, doesn't matter. + if ( ! empty( $bare_array_keys ) ) { + $found_keys = $this->get_array_access_keys( $i ); + $found_keys = array_map( array( $this, 'strip_quotes' ), $found_keys ); + $diff = array_diff_assoc( $bare_array_keys, $found_keys ); + if ( ! empty( $diff ) ) { + continue; + } + } + + return true; + } + + break; + + case 'function_call': + // Only check calls to array_key_exists() and key_exists(). + if ( 'array_key_exists' !== $this->tokens[ $i ]['content'] + && 'key_exists' !== $this->tokens[ $i ]['content'] + ) { + continue 2; + } + + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true, null, true ); + if ( false === $next_non_empty || \T_OPEN_PARENTHESIS !== $this->tokens[ $next_non_empty ]['code'] ) { + // Not a function call. + continue 2; + } + + if ( $this->is_class_object_call( $i ) === true ) { + // Method call. + continue 2; + } + + if ( $this->is_token_namespaced( $i ) === true ) { + // Namespaced function call. + continue 2; + } + + $params = $this->get_function_call_parameters( $i ); + if ( count( $params ) < 2 ) { + continue 2; + } + + $param2_first_token = $this->phpcsFile->findNext( Tokens::$emptyTokens, $params[2]['start'], ( $params[2]['end'] + 1 ), true ); + if ( false === $param2_first_token + || \T_VARIABLE !== $this->tokens[ $param2_first_token ]['code'] + || $this->tokens[ $param2_first_token ]['content'] !== $this->tokens[ $stackPtr ]['content'] + ) { + continue 2; + } + + if ( ! empty( $bare_array_keys ) ) { + // Prevent the original array from being altered. + $bare_keys = $bare_array_keys; + $last_key = array_pop( $bare_keys ); + + /* + * For multi-level array access, the complete set of keys could be split between + * the first and the second parameter, but could also be completely in the second + * parameter, so we need to check both options. + */ + + $found_keys = $this->get_array_access_keys( $param2_first_token ); + $found_keys = array_map( array( $this, 'strip_quotes' ), $found_keys ); + + // First try matching the complete set against the second parameter. + $diff = array_diff_assoc( $bare_array_keys, $found_keys ); + if ( empty( $diff ) ) { + return true; + } + + // If that failed, try getting an exact match for the subset against the + // second parameter and the last key against the first. + if ( $bare_keys === $found_keys && $this->strip_quotes( $params[1]['raw'] ) === $last_key ) { + return true; + } + + // Didn't find the correct array keys. + continue 2; + } + + return true; + + case 'coalesce': + $prev = $i; + do { + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $prev - 1 ), null, true, null, true ); + // Skip over array keys, like $_GET['key']['subkey']. + if ( \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $prev ]['code'] ) { + $prev = $this->tokens[ $prev ]['bracket_opener']; + continue; + } + + break; + } while ( $prev >= ( $scope_start + 1 ) ); + + // We should now have reached the variable. + if ( \T_VARIABLE !== $this->tokens[ $prev ]['code'] ) { + continue 2; + } + + if ( $this->tokens[ $prev ]['content'] !== $this->tokens[ $stackPtr ]['content'] ) { + continue 2; + } + + if ( ! empty( $bare_array_keys ) ) { + $found_keys = $this->get_array_access_keys( $prev ); + $found_keys = array_map( array( $this, 'strip_quotes' ), $found_keys ); + $diff = array_diff_assoc( $bare_array_keys, $found_keys ); + if ( ! empty( $diff ) ) { + continue 2; + } + } + + // Right variable, correct key. + return true; + } + } + + return false; + } + + /** + * Check whether a variable is being compared to another value. + * + * E.g., $var === 'foo', 1 <= $var, etc. + * + * Also recognizes `switch ( $var )`. + * + * @since 0.5.0 + * @since 2.1.0 Added the $include_coalesce parameter. + * + * @param int $stackPtr The index of this token in the stack. + * @param bool $include_coalesce Optional. Whether or not to regard the null + * coalesce operator - ?? - as a comparison operator. + * Defaults to true. + * Null coalesce is a special comparison operator in this + * sense as it doesn't compare a variable to whatever is + * on the other side of the comparison operator. + * + * @return bool Whether this is a comparison. + */ + protected function is_comparison( $stackPtr, $include_coalesce = true ) { + + $comparisonTokens = Tokens::$comparisonTokens; + if ( false === $include_coalesce ) { + unset( $comparisonTokens[ \T_COALESCE ] ); + } + + // We first check if this is a switch statement (switch ( $var )). + if ( isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $close_parenthesis = end( $nested_parenthesis ); + + if ( + isset( $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ) + && \T_SWITCH === $this->tokens[ $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ]['code'] + ) { + return true; + } + } + + // Find the previous non-empty token. We check before the var first because + // yoda conditions are usually expected. + $previous_token = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( isset( $comparisonTokens[ $this->tokens[ $previous_token ]['code'] ] ) ) { + return true; + } + + // Maybe the comparison operator is after this. + $next_token = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $stackPtr + 1 ), + null, + true + ); + + // This might be an opening square bracket in the case of arrays ($var['a']). + while ( false !== $next_token && \T_OPEN_SQUARE_BRACKET === $this->tokens[ $next_token ]['code'] ) { + + $next_token = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $this->tokens[ $next_token ]['bracket_closer'] + 1 ), + null, + true + ); + } + + if ( false !== $next_token && isset( $comparisonTokens[ $this->tokens[ $next_token ]['code'] ] ) ) { + return true; + } + + return false; + } + + /** + * Check if a token is inside of an array-value comparison function. + * + * @since 2.1.0 + * + * @param int $stackPtr The index of the token in the stack. + * + * @return bool Whether the token is (part of) a parameter to an + * array-value comparison function. + */ + protected function is_in_array_comparison( $stackPtr ) { + $function_ptr = $this->is_in_function_call( $stackPtr, $this->arrayCompareFunctions, true, true ); + if ( false === $function_ptr ) { + return false; + } + + $function_name = $this->tokens[ $function_ptr ]['content']; + if ( true === $this->arrayCompareFunctions[ $function_name ] ) { + return true; + } + + if ( $this->get_function_call_parameter_count( $function_ptr ) >= $this->arrayCompareFunctions[ $function_name ] ) { + return true; + } + + return false; + } + + /** + * Check what type of 'use' statement a token is part of. + * + * The T_USE token has multiple different uses: + * + * 1. In a closure: function () use ( $var ) {} + * 2. In a class, to import a trait: use Trait_Name + * 3. In a namespace, to import a class: use Some\Class; + * + * This function will check the token and return 'closure', 'trait', or 'class', + * based on which of these uses the use is being used for. + * + * @since 0.7.0 + * + * @param int $stackPtr The position of the token to check. + * + * @return string The type of use. + */ + protected function get_use_type( $stackPtr ) { + + // USE keywords inside closures. + $next = $this->phpcsFile->findNext( \T_WHITESPACE, ( $stackPtr + 1 ), null, true ); + + if ( \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] ) { + return 'closure'; + } + + // USE keywords for traits. + $valid_scopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_TRAIT' => true, + ); + if ( false !== $this->valid_direct_scope( $stackPtr, $valid_scopes ) ) { + return 'trait'; + } + + // USE keywords for classes to import to a namespace. + return 'class'; + } + + /** + * Get the interpolated variable names from a string. + * + * Check if '$' is followed by a valid variable name, and that it is not preceded by an escape sequence. + * + * @since 0.9.0 + * + * @param string $string The contents of a T_DOUBLE_QUOTED_STRING or T_HEREDOC token. + * + * @return array Variable names (without '$' sigil). + */ + protected function get_interpolated_variables( $string ) { + $variables = array(); + if ( preg_match_all( '/(?P\\\\*)\$(?P\w+)/', $string, $match_sets, \PREG_SET_ORDER ) ) { + foreach ( $match_sets as $matches ) { + if ( ! isset( $matches['backslashes'] ) || ( \strlen( $matches['backslashes'] ) % 2 ) === 0 ) { + $variables[] = $matches['symbol']; + } + } + } + return $variables; + } + + /** + * Strip variables from an arbitrary double quoted/heredoc string. + * + * Intended for use with the contents of a T_DOUBLE_QUOTED_STRING or T_HEREDOC token. + * + * @since 0.14.0 + * + * @param string $string The raw string. + * + * @return string String without variables in it. + */ + public function strip_interpolated_variables( $string ) { + if ( strpos( $string, '$' ) === false ) { + return $string; + } + + return preg_replace( self::REGEX_COMPLEX_VARS, '', $string ); + } + + /** + * Checks if a function call has parameters. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, it + * will detect whether the array has values or is empty. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/120 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/152 + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function does_function_call_have_parameters( $stackPtr ) { + + // Check for the existence of the token. + if ( false === isset( $this->tokens[ $stackPtr ] ) ) { + return false; + } + + // Is this one of the tokens this function handles ? + if ( false === \in_array( $this->tokens[ $stackPtr ]['code'], array( \T_STRING, \T_ARRAY, \T_OPEN_SHORT_ARRAY ), true ) ) { + return false; + } + + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + + // Deal with short array syntax. + if ( 'T_OPEN_SHORT_ARRAY' === $this->tokens[ $stackPtr ]['type'] ) { + if ( false === isset( $this->tokens[ $stackPtr ]['bracket_closer'] ) ) { + return false; + } + + if ( $next_non_empty === $this->tokens[ $stackPtr ]['bracket_closer'] ) { + // No parameters. + return false; + } else { + return true; + } + } + + // Deal with function calls & long arrays. + // Next non-empty token should be the open parenthesis. + if ( false === $next_non_empty && \T_OPEN_PARENTHESIS !== $this->tokens[ $next_non_empty ]['code'] ) { + return false; + } + + if ( false === isset( $this->tokens[ $next_non_empty ]['parenthesis_closer'] ) ) { + return false; + } + + $close_parenthesis = $this->tokens[ $next_non_empty ]['parenthesis_closer']; + $next_next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), ( $close_parenthesis + 1 ), true ); + + if ( $next_next_non_empty === $close_parenthesis ) { + // No parameters. + return false; + } + + return true; + } + + /** + * Count the number of parameters a function call has been passed. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will return the number of values in the array. + * + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/111 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/114 + * @link https://github.com/PHPCompatibility/PHPCompatibility/issues/151 + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return int + */ + public function get_function_call_parameter_count( $stackPtr ) { + if ( false === $this->does_function_call_have_parameters( $stackPtr ) ) { + return 0; + } + + return \count( $this->get_function_call_parameters( $stackPtr ) ); + } + + /** + * Get information on all parameters passed to a function call. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Extra feature: If passed an T_ARRAY or T_OPEN_SHORT_ARRAY stack pointer, + * it will tokenize the values / key/value pairs contained in the array call. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return array Multi-dimentional array with parameter details or + * empty array if no parameters are found. + * + * @type int $position 1-based index position of the parameter. { + * @type int $start Stack pointer for the start of the parameter. + * @type int $end Stack pointer for the end of parameter. + * @type int $raw Trimmed raw parameter content. + * } + */ + public function get_function_call_parameters( $stackPtr ) { + if ( false === $this->does_function_call_have_parameters( $stackPtr ) ) { + return array(); + } + + /* + * Ok, we know we have a T_STRING, T_ARRAY or T_OPEN_SHORT_ARRAY with parameters + * and valid open & close brackets/parenthesis. + */ + + // Mark the beginning and end tokens. + if ( 'T_OPEN_SHORT_ARRAY' === $this->tokens[ $stackPtr ]['type'] ) { + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + + $nestedParenthesisCount = 0; + } else { + $opener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + + $nestedParenthesisCount = 1; + } + + // Which nesting level is the one we are interested in ? + if ( isset( $this->tokens[ $opener ]['nested_parenthesis'] ) ) { + $nestedParenthesisCount += \count( $this->tokens[ $opener ]['nested_parenthesis'] ); + } + + $parameters = array(); + $next_comma = $opener; + $param_start = ( $opener + 1 ); + $cnt = 1; + while ( $next_comma = $this->phpcsFile->findNext( array( \T_COMMA, $this->tokens[ $closer ]['code'], \T_OPEN_SHORT_ARRAY, \T_CLOSURE ), ( $next_comma + 1 ), ( $closer + 1 ) ) ) { + // Ignore anything within short array definition brackets. + if ( 'T_OPEN_SHORT_ARRAY' === $this->tokens[ $next_comma ]['type'] + && ( isset( $this->tokens[ $next_comma ]['bracket_opener'] ) + && $this->tokens[ $next_comma ]['bracket_opener'] === $next_comma ) + && isset( $this->tokens[ $next_comma ]['bracket_closer'] ) + ) { + // Skip forward to the end of the short array definition. + $next_comma = $this->tokens[ $next_comma ]['bracket_closer']; + continue; + } + + // Skip past closures passed as function parameters. + if ( 'T_CLOSURE' === $this->tokens[ $next_comma ]['type'] + && ( isset( $this->tokens[ $next_comma ]['scope_condition'] ) + && $this->tokens[ $next_comma ]['scope_condition'] === $next_comma ) + && isset( $this->tokens[ $next_comma ]['scope_closer'] ) + ) { + // Skip forward to the end of the closure declaration. + $next_comma = $this->tokens[ $next_comma ]['scope_closer']; + continue; + } + + // Ignore comma's at a lower nesting level. + if ( \T_COMMA === $this->tokens[ $next_comma ]['code'] + && isset( $this->tokens[ $next_comma ]['nested_parenthesis'] ) + && \count( $this->tokens[ $next_comma ]['nested_parenthesis'] ) !== $nestedParenthesisCount + ) { + continue; + } + + // Ignore closing parenthesis/bracket if not 'ours'. + if ( $this->tokens[ $next_comma ]['type'] === $this->tokens[ $closer ]['type'] && $next_comma !== $closer ) { + continue; + } + + // Ok, we've reached the end of the parameter. + $parameters[ $cnt ]['start'] = $param_start; + $parameters[ $cnt ]['end'] = ( $next_comma - 1 ); + $parameters[ $cnt ]['raw'] = trim( $this->phpcsFile->getTokensAsString( $param_start, ( $next_comma - $param_start ) ) ); + + /* + * Check if there are more tokens before the closing parenthesis. + * Prevents code like the following from setting a third parameter: + * functionCall( $param1, $param2, ); + */ + $has_next_param = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_comma + 1 ), $closer, true, null, true ); + if ( false === $has_next_param ) { + break; + } + + // Prepare for the next parameter. + $param_start = ( $next_comma + 1 ); + $cnt++; + } + + return $parameters; + } + + /** + * Get information on a specific parameter passed to a function call. + * + * Expects to be passed the T_STRING stack pointer for the function call. + * If passed a T_STRING which is *not* a function call, the behaviour is unreliable. + * + * Will return a array with the start token pointer, end token pointer and the raw value + * of the parameter at a specific offset. + * If the specified parameter is not found, will return false. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the function call token. + * @param int $param_offset The 1-based index position of the parameter to retrieve. + * + * @return array|false + */ + public function get_function_call_parameter( $stackPtr, $param_offset ) { + $parameters = $this->get_function_call_parameters( $stackPtr ); + + if ( false === isset( $parameters[ $param_offset ] ) ) { + return false; + } + + return $parameters[ $param_offset ]; + } + + /** + * Find the array opener & closer based on a T_ARRAY or T_OPEN_SHORT_ARRAY token. + * + * @since 0.12.0 + * + * @param int $stackPtr The stack pointer to the array token. + * + * @return array|bool Array with two keys `opener`, `closer` or false if + * either or these could not be determined. + */ + protected function find_array_open_close( $stackPtr ) { + /* + * Determine the array opener & closer. + */ + if ( \T_ARRAY === $this->tokens[ $stackPtr ]['code'] ) { + if ( isset( $this->tokens[ $stackPtr ]['parenthesis_opener'] ) ) { + $opener = $this->tokens[ $stackPtr ]['parenthesis_opener']; + + if ( isset( $this->tokens[ $opener ]['parenthesis_closer'] ) ) { + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + } + } + } else { + // Short array syntax. + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + } + + if ( isset( $opener, $closer ) ) { + return array( + 'opener' => $opener, + 'closer' => $closer, + ); + } + + return false; + } + + /** + * Find the list opener & closer based on a T_LIST or T_OPEN_SHORT_ARRAY token. + * + * @since 2.2.0 + * + * @param int $stackPtr The stack pointer to the array token. + * + * @return array|bool Array with two keys `opener`, `closer` or false if + * not a (short) list token or if either or these + * could not be determined. + */ + protected function find_list_open_close( $stackPtr ) { + /* + * Determine the list opener & closer. + */ + if ( \T_LIST === $this->tokens[ $stackPtr ]['code'] ) { + // PHPCS 3.5.0. + if ( isset( $this->tokens[ $stackPtr ]['parenthesis_opener'] ) ) { + $opener = $this->tokens[ $stackPtr ]['parenthesis_opener']; + + } else { + // PHPCS < 3.5.0. + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false !== $next_non_empty + && \T_OPEN_PARENTHESIS === $this->tokens[ $next_non_empty ]['code'] + ) { + $opener = $next_non_empty; + } + } + + if ( isset( $opener, $this->tokens[ $opener ]['parenthesis_closer'] ) ) { + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + } + } + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) === true + ) { + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + } + + if ( isset( $opener, $closer ) ) { + return array( + 'opener' => $opener, + 'closer' => $closer, + ); + } + + return false; + } + + /** + * Determine the namespace name an arbitrary token lives in. + * + * @since 0.10.0 + * @since 0.12.0 Moved from the `AbstractClassRestrictionsSniff` to this class. + * + * @param int $stackPtr The token position for which to determine the namespace. + * + * @return string Namespace name or empty string if it couldn't be determined or no namespace applies. + */ + public function determine_namespace( $stackPtr ) { + + // Check for the existence of the token. + if ( ! isset( $this->tokens[ $stackPtr ] ) ) { + return ''; + } + + // Check for scoped namespace {}. + if ( ! empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + $namespacePtr = $this->phpcsFile->getCondition( $stackPtr, \T_NAMESPACE ); + if ( false !== $namespacePtr ) { + $namespace = $this->get_declared_namespace_name( $namespacePtr ); + if ( false !== $namespace ) { + return $namespace; + } + + // We are in a scoped namespace, but couldn't determine the name. + // Searching for a global namespace is futile. + return ''; + } + } + + /* + * Not in a scoped namespace, so let's see if we can find a non-scoped namespace instead. + * Keeping in mind that: + * - there can be multiple non-scoped namespaces in a file (bad practice, but it happens). + * - the namespace keyword can also be used as part of a function/method call and such. + * - that a non-named namespace resolves to the global namespace. + */ + $previousNSToken = $stackPtr; + $namespace = false; + do { + $previousNSToken = $this->phpcsFile->findPrevious( \T_NAMESPACE, ( $previousNSToken - 1 ) ); + + // Stop if we encounter a scoped namespace declaration as we already know we're not in one. + if ( ! empty( $this->tokens[ $previousNSToken ]['scope_condition'] ) + && $this->tokens[ $previousNSToken ]['scope_condition'] === $previousNSToken + ) { + break; + } + + $namespace = $this->get_declared_namespace_name( $previousNSToken ); + + } while ( false === $namespace && false !== $previousNSToken ); + + // If we still haven't got a namespace, return an empty string. + if ( false === $namespace ) { + return ''; + } + + return $namespace; + } + + /** + * Get the complete namespace name for a namespace declaration. + * + * For hierarchical namespaces, the name will be composed of several tokens, + * i.e. MyProject\Sub\Level which will be returned together as one string. + * + * @since 0.12.0 A lesser variant of this method previously existed in the + * `AbstractClassRestrictionsSniff` class. + * + * @param int|bool $stackPtr The position of a T_NAMESPACE token. + * + * @return string|false Namespace name or false if not a namespace declaration. + * Namespace name can be an empty string for global namespace declaration. + */ + public function get_declared_namespace_name( $stackPtr ) { + + // Check for the existence of the token. + if ( false === $stackPtr || ! isset( $this->tokens[ $stackPtr ] ) ) { + return false; + } + + if ( \T_NAMESPACE !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( \T_NS_SEPARATOR === $this->tokens[ $nextToken ]['code'] ) { + // Not a namespace declaration, but use of, i.e. `namespace\someFunction();`. + return false; + } + + if ( \T_OPEN_CURLY_BRACKET === $this->tokens[ $nextToken ]['code'] ) { + // Declaration for global namespace when using multiple namespaces in a file. + // I.e.: `namespace {}`. + return ''; + } + + // Ok, this should be a namespace declaration, so get all the parts together. + $acceptedTokens = array( + \T_STRING => true, + \T_NS_SEPARATOR => true, + ); + $validTokens = $acceptedTokens + Tokens::$emptyTokens; + + $namespaceName = ''; + while ( isset( $validTokens[ $this->tokens[ $nextToken ]['code'] ] ) ) { + if ( isset( $acceptedTokens[ $this->tokens[ $nextToken ]['code'] ] ) ) { + $namespaceName .= trim( $this->tokens[ $nextToken ]['content'] ); + } + ++$nextToken; + } + + return $namespaceName; + } + + /** + * Check whether a T_CONST token is a class constant declaration. + * + * @since 0.14.0 + * + * @param int $stackPtr The position in the stack of the T_CONST token to verify. + * + * @return bool + */ + public function is_class_constant( $stackPtr ) { + if ( ! isset( $this->tokens[ $stackPtr ] ) || \T_CONST !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + // Note: traits can not declare constants. + $valid_scopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_INTERFACE' => true, + ); + + return is_int( $this->valid_direct_scope( $stackPtr, $valid_scopes ) ); + } + + /** + * Check whether a T_VARIABLE token is a class property declaration. + * + * @since 0.14.0 + * + * @param int $stackPtr The position in the stack of the T_VARIABLE token to verify. + * + * @return bool + */ + public function is_class_property( $stackPtr ) { + if ( ! isset( $this->tokens[ $stackPtr ] ) || \T_VARIABLE !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + // Note: interfaces can not declare properties. + $valid_scopes = array( + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_TRAIT' => true, + ); + + $scopePtr = $this->valid_direct_scope( $stackPtr, $valid_scopes ); + if ( false !== $scopePtr ) { + // Make sure it's not a method parameter. + if ( empty( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return true; + } else { + $parenthesis = array_keys( $this->tokens[ $stackPtr ]['nested_parenthesis'] ); + $deepest_open = array_pop( $parenthesis ); + if ( $deepest_open < $scopePtr + || isset( $this->tokens[ $deepest_open ]['parenthesis_owner'] ) === false + || \T_FUNCTION !== $this->tokens[ $this->tokens[ $deepest_open ]['parenthesis_owner'] ]['code'] + ) { + return true; + } + } + } + + return false; + } + + /** + * Check whether the direct wrapping scope of a token is within a limited set of + * acceptable tokens. + * + * Used to check, for instance, if a T_CONST is a class constant. + * + * @since 0.14.0 + * + * @param int $stackPtr The position in the stack of the token to verify. + * @param array $valid_scopes Array of token types. + * Keys should be the token types in string format + * to allow for newer token types. + * Value is irrelevant. + * + * @return int|bool StackPtr to the scope if valid, false otherwise. + */ + protected function valid_direct_scope( $stackPtr, array $valid_scopes ) { + if ( empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + return false; + } + + /* + * Check only the direct wrapping scope of the token. + */ + $conditions = array_keys( $this->tokens[ $stackPtr ]['conditions'] ); + $ptr = array_pop( $conditions ); + + if ( ! isset( $this->tokens[ $ptr ] ) ) { + return false; + } + + if ( isset( $valid_scopes[ $this->tokens[ $ptr ]['type'] ] ) ) { + return $ptr; + } + + return false; + } + + /** + * Checks whether this is a call to a $wpdb method that we want to sniff. + * + * If available in the child class, the $methodPtr, $i and $end properties are + * automatically set to correspond to the start and end of the method call. + * The $i property is also set if this is not a method call but rather the + * use of a $wpdb property. + * + * @since 0.8.0 + * @since 0.9.0 The return value is now always boolean. The $end and $i member + * vars are automatically updated. + * @since 0.14.0 Moved this method from the `PreparedSQL` sniff to the base WP sniff. + * + * {@internal This method should probably be refactored.}} + * + * @param int $stackPtr The index of the $wpdb variable. + * @param array $target_methods Array of methods. Key(s) should be method name. + * + * @return bool Whether this is a $wpdb method call. + */ + protected function is_wpdb_method_call( $stackPtr, $target_methods ) { + + // Check for wpdb. + if ( ( \T_VARIABLE === $this->tokens[ $stackPtr ]['code'] && '$wpdb' !== $this->tokens[ $stackPtr ]['content'] ) + || ( \T_STRING === $this->tokens[ $stackPtr ]['code'] && 'wpdb' !== $this->tokens[ $stackPtr ]['content'] ) + ) { + return false; + } + + // Check that this is a method call. + $is_object_call = $this->phpcsFile->findNext( + array( \T_OBJECT_OPERATOR, \T_DOUBLE_COLON ), + ( $stackPtr + 1 ), + null, + false, + null, + true + ); + if ( false === $is_object_call ) { + return false; + } + + $methodPtr = $this->phpcsFile->findNext( \T_WHITESPACE, ( $is_object_call + 1 ), null, true, null, true ); + if ( false === $methodPtr ) { + return false; + } + + if ( \T_STRING === $this->tokens[ $methodPtr ]['code'] && property_exists( $this, 'methodPtr' ) ) { + $this->methodPtr = $methodPtr; + } + + // Find the opening parenthesis. + $opening_paren = $this->phpcsFile->findNext( \T_WHITESPACE, ( $methodPtr + 1 ), null, true, null, true ); + + if ( false === $opening_paren ) { + return false; + } + + if ( property_exists( $this, 'i' ) ) { + $this->i = $opening_paren; + } + + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $opening_paren ]['code'] + || ! isset( $this->tokens[ $opening_paren ]['parenthesis_closer'] ) + ) { + return false; + } + + // Check that this is one of the methods that we are interested in. + if ( ! isset( $target_methods[ $this->tokens[ $methodPtr ]['content'] ] ) ) { + return false; + } + + // Find the end of the first parameter. + $end = $this->phpcsFile->findEndOfStatement( $opening_paren + 1 ); + + if ( \T_COMMA !== $this->tokens[ $end ]['code'] ) { + ++$end; + } + + if ( property_exists( $this, 'end' ) ) { + $this->end = $end; + } + + return true; + } + + /** + * Determine whether an arbitrary T_STRING token is the use of a global constant. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the function call token. + * + * @return bool + */ + public function is_use_of_global_constant( $stackPtr ) { + // Check for the existence of the token. + if ( ! isset( $this->tokens[ $stackPtr ] ) ) { + return false; + } + + // Is this one of the tokens this function handles ? + if ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] ) { + return false; + } + + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false !== $next + && ( \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] + || \T_DOUBLE_COLON === $this->tokens[ $next ]['code'] ) + ) { + // Function call or declaration. + return false; + } + + // Array of tokens which if found preceding the $stackPtr indicate that a T_STRING is not a global constant. + $tokens_to_ignore = array( + 'T_NAMESPACE' => true, + 'T_USE' => true, + 'T_CLASS' => true, + 'T_TRAIT' => true, + 'T_INTERFACE' => true, + 'T_EXTENDS' => true, + 'T_IMPLEMENTS' => true, + 'T_NEW' => true, + 'T_FUNCTION' => true, + 'T_DOUBLE_COLON' => true, + 'T_OBJECT_OPERATOR' => true, + 'T_INSTANCEOF' => true, + 'T_INSTEADOF' => true, + 'T_GOTO' => true, + 'T_AS' => true, + 'T_PUBLIC' => true, + 'T_PROTECTED' => true, + 'T_PRIVATE' => true, + ); + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false !== $prev + && isset( $tokens_to_ignore[ $this->tokens[ $prev ]['type'] ] ) + ) { + // Not the use of a constant. + return false; + } + + if ( $this->is_token_namespaced( $stackPtr ) === true ) { + // Namespaced constant of the same name. + return false; + } + + if ( false !== $prev + && \T_CONST === $this->tokens[ $prev ]['code'] + && $this->is_class_constant( $prev ) + ) { + // Class constant declaration of the same name. + return false; + } + + /* + * Deal with a number of variations of use statements. + */ + for ( $i = $stackPtr; $i > 0; $i-- ) { + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $stackPtr ]['line'] ) { + break; + } + } + + $firstOnLine = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( false !== $firstOnLine && \T_USE === $this->tokens[ $firstOnLine ]['code'] ) { + $nextOnLine = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $firstOnLine + 1 ), null, true ); + if ( false !== $nextOnLine ) { + if ( \T_STRING === $this->tokens[ $nextOnLine ]['code'] + && 'const' === $this->tokens[ $nextOnLine ]['content'] + ) { + $hasNsSep = $this->phpcsFile->findNext( \T_NS_SEPARATOR, ( $nextOnLine + 1 ), $stackPtr ); + if ( false !== $hasNsSep ) { + // Namespaced const (group) use statement. + return false; + } + } else { + // Not a const use statement. + return false; + } + } + } + + return true; + } + + /** + * Determine if a variable is in the `as $key => $value` part of a foreach condition. + * + * @since 1.0.0 + * @since 1.1.0 Moved from the PrefixAllGlobals sniff to the Sniff base class. + * + * @param int $stackPtr Pointer to the variable. + * + * @return bool True if it is. False otherwise. + */ + protected function is_foreach_as( $stackPtr ) { + if ( ! isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + return false; + } + + $nested_parenthesis = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $close_parenthesis = end( $nested_parenthesis ); + $open_parenthesis = key( $nested_parenthesis ); + if ( ! isset( $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ) ) { + return false; + } + + if ( \T_FOREACH !== $this->tokens[ $this->tokens[ $close_parenthesis ]['parenthesis_owner'] ]['code'] ) { + return false; + } + + $as_ptr = $this->phpcsFile->findNext( \T_AS, ( $open_parenthesis + 1 ), $close_parenthesis ); + if ( false === $as_ptr ) { + // Should never happen. + return false; + } + + return ( $stackPtr > $as_ptr ); + } + + /** + * Determine whether a T_OPEN/CLOSE_SHORT_ARRAY token is a short list() construct. + * + * @internal This function will be introduced in PHPCS upstream in version 3.5.0 + * and can be removed from WPCS once WPCS raises the minimum version. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the array bracket token. + * + * @return bool True if the token passed is the open/close bracket of a short list. + * False if the token is a short array bracket or not + * a T_OPEN/CLOSE_SHORT_ARRAY token. + */ + protected function is_short_list( $stackPtr ) { + // Is this one of the tokens this function handles ? + if ( \T_OPEN_SHORT_ARRAY !== $this->tokens[ $stackPtr ]['code'] + && \T_CLOSE_SHORT_ARRAY !== $this->tokens[ $stackPtr ]['code'] + ) { + return false; + } + + switch ( $this->tokens[ $stackPtr ]['code'] ) { + case \T_OPEN_SHORT_ARRAY: + $opener = $stackPtr; + $closer = $this->tokens[ $stackPtr ]['bracket_closer']; + break; + + case \T_CLOSE_SHORT_ARRAY: + $opener = $this->tokens[ $stackPtr ]['bracket_opener']; + $closer = $stackPtr; + break; + } + + $nextNonEmpty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $closer + 1 ), null, true, null, true ); + if ( false !== $nextNonEmpty && \T_EQUAL === $this->tokens[ $nextNonEmpty ]['code'] ) { + return true; + } + + // Check for short list in foreach, i.e. `foreach($array as [$a, $b])`. + if ( $this->is_foreach_as( $stackPtr ) === true ) { + return true; + } + + // Maybe this is a short list syntax nested inside another short list syntax ? + $parentOpen = $opener; + do { + $parentOpen = $this->phpcsFile->findPrevious( + \T_OPEN_SHORT_ARRAY, + ( $parentOpen - 1 ), + null, + false, + null, + true + ); + + if ( false === $parentOpen ) { + return false; + } + } while ( $this->tokens[ $parentOpen ]['bracket_closer'] < $opener ); + + return $this->is_short_list( $parentOpen ); + } + + /** + * Get a list of the token pointers to the variables being assigned to in a list statement. + * + * @internal No need to take special measures for nested lists. Nested or not, + * each list part can only contain one variable being written to. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the T_LIST or T_OPEN_SHORT_ARRAY + * token in the stack. + * @param array $list_open_close Optional. Array containing the token pointers to + * the list opener and closer. + * + * @return array Array with the stack pointers to the variables or an empty + * array when not a (short) list. + */ + protected function get_list_variables( $stackPtr, $list_open_close = array() ) { + if ( \T_LIST !== $this->tokens[ $stackPtr ]['code'] + && \T_OPEN_SHORT_ARRAY !== $this->tokens[ $stackPtr ]['code'] + ) { + return array(); + } + + if ( empty( $list_open_close ) ) { + $list_open_close = $this->find_list_open_close( $stackPtr ); + if ( false === $list_open_close ) { + // Not a (short) list. + return array(); + } + } + + $var_pointers = array(); + $current = $list_open_close['opener']; + $closer = $list_open_close['closer']; + $last = false; + do { + ++$current; + $next_comma = $this->phpcsFile->findNext( \T_COMMA, $current, $closer ); + if ( false === $next_comma ) { + $next_comma = $closer; + $last = true; + } + + // Skip over the "key" part in keyed lists. + $arrow = $this->phpcsFile->findNext( \T_DOUBLE_ARROW, $current, $next_comma ); + if ( false !== $arrow ) { + $current = ( $arrow + 1 ); + } + + /* + * Each list item can only have one variable to which an assignment is being made. + * This can be an array with a (variable) index, but that doesn't matter, we're only + * concerned with the actual variable. + */ + $var = $this->phpcsFile->findNext( \T_VARIABLE, $current, $next_comma ); + if ( false !== $var ) { + // Not an empty list item. + $var_pointers[] = $var; + } + + $current = $next_comma; + + } while ( false === $last ); + + return $var_pointers; + } + + /** + * Check whether a function has been marked as deprecated via a @deprecated tag + * in the function docblock. + * + * {@internal This method is static to allow the ValidFunctionName class to use it.}} + * + * @since 2.2.0 + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of a T_FUNCTION + * token in the stack. + * + * @return bool + */ + public static function is_function_deprecated( File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = \T_WHITESPACE; + + $comment_end = $phpcsFile->findPrevious( $find, ( $stackPtr - 1 ), null, true ); + if ( \T_DOC_COMMENT_CLOSE_TAG !== $tokens[ $comment_end ]['code'] ) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return false; + } + + $comment_start = $tokens[ $comment_end ]['comment_opener']; + foreach ( $tokens[ $comment_start ]['comment_tags'] as $tag ) { + if ( '@deprecated' === $tokens[ $tag ]['content'] ) { + return true; + } + } + + return false; + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php new file mode 100644 index 000000000..5488bfd3b --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayDeclarationSpacingSniff.php @@ -0,0 +1,468 @@ + \T_ARRAY, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.12.0 + * + * @return array + */ + public function register() { + return $this->targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.12.0 The actual checks contained in this method used to + * be in the `processSingleLineArray()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + unset( $array_open_close ); + + /* + * Long arrays only: Check for space between the array keyword and the open parenthesis. + */ + if ( \T_ARRAY === $this->tokens[ $stackPtr ]['code'] ) { + + if ( ( $stackPtr + 1 ) !== $opener ) { + $error = 'There must be no space between the "array" keyword and the opening parenthesis'; + $error_code = 'SpaceAfterKeyword'; + + $nextNonWhitespace = $this->phpcsFile->findNext( \T_WHITESPACE, ( $stackPtr + 1 ), ( $opener + 1 ), true ); + if ( $nextNonWhitespace !== $opener ) { + // Don't auto-fix: Something other than whitespace found between keyword and open parenthesis. + $this->phpcsFile->addError( $error, $stackPtr, $error_code ); + } else { + + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, $error_code ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = ( $stackPtr + 1 ); $i < $opener; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + unset( $i ); + } + } + unset( $error, $error_code, $nextNonWhitespace, $fix ); + } + } + + /* + * Check for empty arrays. + */ + $nextNonWhitespace = $this->phpcsFile->findNext( \T_WHITESPACE, ( $opener + 1 ), ( $closer + 1 ), true ); + if ( $nextNonWhitespace === $closer ) { + + if ( ( $opener + 1 ) !== $closer ) { + $fix = $this->phpcsFile->addFixableError( + 'Empty array declaration must have no space between the parentheses', + $stackPtr, + 'SpaceInEmptyArray' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = ( $opener + 1 ); $i < $closer; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + unset( $i ); + } + } + + // This array is empty, so the below checks aren't necessary. + return; + } + unset( $nextNonWhitespace ); + + // Pass off to either the single line or multi-line array analysis. + if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) { + $this->process_single_line_array( $stackPtr, $opener, $closer ); + } else { + $this->process_multi_line_array( $stackPtr, $opener, $closer ); + } + } + + /** + * Process a single-line array. + * + * @since 0.13.0 The actual checks contained in this method used to + * be in the `process()` method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return void + */ + protected function process_single_line_array( $stackPtr, $opener, $closer ) { + /* + * Check that associative arrays are always multi-line. + */ + $array_has_keys = $this->phpcsFile->findNext( \T_DOUBLE_ARROW, $opener, $closer ); + if ( false !== $array_has_keys ) { + + $array_items = $this->get_function_call_parameters( $stackPtr ); + + if ( ( false === $this->allow_single_item_single_line_associative_arrays + && ! empty( $array_items ) ) + || ( true === $this->allow_single_item_single_line_associative_arrays + && \count( $array_items ) > 1 ) + ) { + /* + * Make sure the double arrow is for *this* array, not for a nested one. + */ + $array_has_keys = false; // Reset before doing more detailed check. + foreach ( $array_items as $item ) { + for ( $ptr = $item['start']; $ptr <= $item['end']; $ptr++ ) { + if ( \T_DOUBLE_ARROW === $this->tokens[ $ptr ]['code'] ) { + $array_has_keys = true; + break 2; + } + + // Skip passed any nested arrays. + if ( isset( $this->targets[ $this->tokens[ $ptr ]['code'] ] ) ) { + $nested_array_open_close = $this->find_array_open_close( $ptr ); + if ( false === $nested_array_open_close ) { + // Nested array open/close could not be determined. + continue; + } + + $ptr = $nested_array_open_close['closer']; + } + } + } + + if ( true === $array_has_keys ) { + + $phrase = 'an'; + if ( true === $this->allow_single_item_single_line_associative_arrays ) { + $phrase = 'a multi-item'; + } + $fix = $this->phpcsFile->addFixableError( + 'When %s array uses associative keys, each value should start on a new line.', + $closer, + 'AssociativeArrayFound', + array( $phrase ) + ); + + if ( true === $fix ) { + + $this->phpcsFile->fixer->beginChangeset(); + + foreach ( $array_items as $item ) { + /* + * Add a line break before the first non-empty token in the array item. + * Prevents extraneous whitespace at the start of the line which could be + * interpreted as alignment whitespace. + */ + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $item['start'], + ( $item['end'] + 1 ), + true + ); + if ( false === $first_non_empty ) { + continue; + } + + if ( $item['start'] <= ( $first_non_empty - 1 ) + && \T_WHITESPACE === $this->tokens[ ( $first_non_empty - 1 ) ]['code'] + ) { + // Remove whitespace which would otherwise becoming trailing + // (as it gives problems with the fixed file). + $this->phpcsFile->fixer->replaceToken( ( $first_non_empty - 1 ), '' ); + } + + $this->phpcsFile->fixer->addNewlineBefore( $first_non_empty ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + + // No need to check for spacing around opener/closer as this array should be multi-line. + return; + } + } + } + + /* + * Check that there is a single space after the array opener and before the array closer. + */ + if ( \T_WHITESPACE !== $this->tokens[ ( $opener + 1 ) ]['code'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Missing space after array opener.', + $opener, + 'NoSpaceAfterArrayOpener' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $opener, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ ( $opener + 1 ) ]['content'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space after array opener, found %s.', + $opener, + 'SpaceAfterArrayOpener', + array( \strlen( $this->tokens[ ( $opener + 1 ) ]['content'] ) ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $opener + 1 ), ' ' ); + } + } + + if ( \T_WHITESPACE !== $this->tokens[ ( $closer - 1 ) ]['code'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Missing space before array closer.', + $closer, + 'NoSpaceBeforeArrayCloser' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $closer, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ ( $closer - 1 ) ]['content'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space before array closer, found %s.', + $closer, + 'SpaceBeforeArrayCloser', + array( \strlen( $this->tokens[ ( $closer - 1 ) ]['content'] ) ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $closer - 1 ), ' ' ); + } + } + } + + /** + * Process a multi-line array. + * + * @since 0.13.0 The actual checks contained in this method used to + * be in the `ArrayDeclaration` sniff. + * + * @param int $stackPtr The position of the current token in the stack. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return void + */ + protected function process_multi_line_array( $stackPtr, $opener, $closer ) { + /* + * Check that the closing bracket is on a new line. + */ + $last_content = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $closer - 1 ), $opener, true ); + if ( false !== $last_content + && $this->tokens[ $last_content ]['line'] === $this->tokens[ $closer ]['line'] + ) { + $fix = $this->phpcsFile->addFixableError( + 'Closing parenthesis of array declaration must be on a new line', + $closer, + 'CloseBraceNewLine' + ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + if ( $last_content < ( $closer - 1 ) + && \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] + ) { + // Remove whitespace which would otherwise becoming trailing + // (as it gives problems with the fixed file). + $this->phpcsFile->fixer->replaceToken( ( $closer - 1 ), '' ); + } + + $this->phpcsFile->fixer->addNewlineBefore( $closer ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + /* + * Check that each array item starts on a new line. + */ + $array_items = $this->get_function_call_parameters( $stackPtr ); + $end_of_last_item = $opener; + + foreach ( $array_items as $item ) { + $end_of_this_item = ( $item['end'] + 1 ); + + // Find the line on which the item starts. + $first_content = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $item['start'], + $end_of_this_item, + true + ); + + // Ignore comments after array items if the next real content starts on a new line. + if ( $this->tokens[ $first_content ]['line'] === $this->tokens[ $end_of_last_item ]['line'] + && ( \T_COMMENT === $this->tokens[ $first_content ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $first_content ]['code'] ] ) ) + ) { + $end_of_comment = $first_content; + + // Find the end of (multi-line) /* */- style trailing comments. + if ( substr( ltrim( $this->tokens[ $end_of_comment ]['content'] ), 0, 2 ) === '/*' ) { + while ( ( \T_COMMENT === $this->tokens[ $end_of_comment ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $end_of_comment ]['code'] ] ) ) + && substr( rtrim( $this->tokens[ $end_of_comment ]['content'] ), -2 ) !== '*/' + && ( $end_of_comment + 1 ) < $end_of_this_item + ) { + $end_of_comment++; + } + + if ( $this->tokens[ $end_of_comment ]['line'] !== $this->tokens[ $end_of_last_item ]['line'] ) { + // Multi-line trailing comment. + $end_of_last_item = $end_of_comment; + } + } + + $next = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + ( $end_of_comment + 1 ), + $end_of_this_item, + true + ); + + if ( false === $next ) { + // Shouldn't happen, but just in case. + $end_of_last_item = $end_of_this_item; + continue; + } + + if ( $this->tokens[ $next ]['line'] !== $this->tokens[ $first_content ]['line'] ) { + $first_content = $next; + } + } + + if ( false === $first_content ) { + // Shouldn't happen, but just in case. + $end_of_last_item = $end_of_this_item; + continue; + } + + if ( $this->tokens[ $end_of_last_item ]['line'] === $this->tokens[ $first_content ]['line'] ) { + + $fix = $this->phpcsFile->addFixableError( + 'Each item in a multi-line array must be on a new line', + $first_content, + 'ArrayItemNoNewLine' + ); + + if ( true === $fix ) { + + $this->phpcsFile->fixer->beginChangeset(); + + if ( ( $end_of_last_item + 1 ) <= ( $first_content - 1 ) + && \T_WHITESPACE === $this->tokens[ ( $first_content - 1 ) ]['code'] + ) { + // Remove whitespace which would otherwise becoming trailing + // (as it gives problems with the fixed file). + $this->phpcsFile->fixer->replaceToken( ( $first_content - 1 ), '' ); + } + + $this->phpcsFile->fixer->addNewlineBefore( $first_content ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + $end_of_last_item = $end_of_this_item; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php new file mode 100644 index 000000000..c0b5dcf57 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayIndentationSniff.php @@ -0,0 +1,542 @@ +ignore_tokens = Tokens::$heredocTokens; + unset( $this->ignore_tokens[ \T_START_HEREDOC ], $this->ignore_tokens[ \T_START_NOWDOC ] ); + $this->ignore_tokens[ \T_INLINE_HTML ] = \T_INLINE_HTML; + + return array( + \T_ARRAY, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + if ( ! isset( $this->tab_width ) ) { + $this->tab_width = PHPCSHelper::get_tab_width( $this->phpcsFile ); + } + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + + if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) { + // Not interested in single line arrays. + return; + } + + /* + * Check the closing bracket is lined up with the start of the content on the line + * containing the array opener. + */ + $opener_line_spaces = $this->get_indentation_size( $opener ); + $closer_line_spaces = ( $this->tokens[ $closer ]['column'] - 1 ); + + if ( $closer_line_spaces !== $opener_line_spaces ) { + $error = 'Array closer not aligned correctly; expected %s space(s) but found %s'; + $error_code = 'CloseBraceNotAligned'; + + /* + * Report & fix the issue if the close brace is on its own line with + * nothing or only indentation whitespace before it. + */ + if ( 0 === $closer_line_spaces + || ( \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] + && 1 === $this->tokens[ ( $closer - 1 ) ]['column'] ) + ) { + $this->add_array_alignment_error( + $closer, + $error, + $error_code, + $opener_line_spaces, + $closer_line_spaces, + $this->get_indentation_string( $opener_line_spaces ) + ); + } else { + /* + * Otherwise, only report the error, don't try and fix it (yet). + * + * It will get corrected in a future loop of the fixer once the closer + * has been moved to its own line by the `ArrayDeclarationSpacing` sniff. + */ + $this->phpcsFile->addError( + $error, + $closer, + $error_code, + array( $opener_line_spaces, $closer_line_spaces ) + ); + } + + unset( $error, $error_code ); + } + + /* + * Verify & correct the array item indentation. + */ + $array_items = $this->get_function_call_parameters( $stackPtr ); + if ( empty( $array_items ) ) { + // Strange, no array items found. + return; + } + + $expected_spaces = ( $opener_line_spaces + $this->tab_width ); + $expected_indent = $this->get_indentation_string( $expected_spaces ); + $end_of_previous_item = $opener; + + foreach ( $array_items as $item ) { + $end_of_this_item = ( $item['end'] + 1 ); + + // Find the line on which the item starts. + $first_content = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $item['start'], + $end_of_this_item, + true + ); + + // Deal with trailing comments. + if ( false !== $first_content + && \T_COMMENT === $this->tokens[ $first_content ]['code'] + && $this->tokens[ $first_content ]['line'] === $this->tokens[ $end_of_previous_item ]['line'] + ) { + $first_content = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE, \T_COMMENT ), + ( $first_content + 1 ), + $end_of_this_item, + true + ); + } + + if ( false === $first_content ) { + $end_of_previous_item = $end_of_this_item; + continue; + } + + // Bow out from reporting and fixing mixed multi-line/single-line arrays. + // That is handled by the ArrayDeclarationSpacingSniff. + if ( $this->tokens[ $first_content ]['line'] === $this->tokens[ $end_of_previous_item ]['line'] + || ( 1 !== $this->tokens[ $first_content ]['column'] + && \T_WHITESPACE !== $this->tokens[ ( $first_content - 1 ) ]['code'] ) + ) { + return $closer; + } + + $found_spaces = ( $this->tokens[ $first_content ]['column'] - 1 ); + + if ( $found_spaces !== $expected_spaces ) { + $this->add_array_alignment_error( + $first_content, + 'Array item not aligned correctly; expected %s spaces but found %s', + 'ItemNotAligned', + $expected_spaces, + $found_spaces, + $expected_indent + ); + } + + // No need for further checking if this is a one-line array item. + if ( $this->tokens[ $first_content ]['line'] === $this->tokens[ $item['end'] ]['line'] ) { + $end_of_previous_item = $end_of_this_item; + continue; + } + + /* + * Multi-line array items. + * + * Verify & if needed, correct the indentation of subsequent lines. + * Subsequent lines may be indented more or less than the mimimum expected indent, + * but the "first line after" should be indented - at least - as much as the very first line + * of the array item. + * Indentation correction for subsequent lines will be based on that diff. + */ + + // Find first token on second line of the array item. + // If the second line is a heredoc/nowdoc, continue on until we find a line with a different token. + // Same for the second line of a multi-line text string. + for ( $ptr = ( $first_content + 1 ); $ptr <= $item['end']; $ptr++ ) { + if ( $this->tokens[ $first_content ]['line'] !== $this->tokens[ $ptr ]['line'] + && 1 === $this->tokens[ $ptr ]['column'] + && false === $this->ignore_token( $ptr ) + ) { + break; + } + } + + $first_content_on_line2 = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $ptr, + $end_of_this_item, + true + ); + + if ( false === $first_content_on_line2 ) { + /* + * Apparently there were only tokens in the ignore list on subsequent lines. + * + * In that case, the comma after the array item might be on a line by itself, + * so check its placement. + */ + if ( $this->tokens[ $item['end'] ]['line'] !== $this->tokens[ $end_of_this_item ]['line'] + && \T_COMMA === $this->tokens[ $end_of_this_item ]['code'] + && ( $this->tokens[ $end_of_this_item ]['column'] - 1 ) !== $expected_spaces + ) { + $this->add_array_alignment_error( + $end_of_this_item, + 'Comma after multi-line array item not aligned correctly; expected %s spaces, but found %s', + 'MultiLineArrayItemCommaNotAligned', + $expected_spaces, + ( $this->tokens[ $end_of_this_item ]['column'] - 1 ), + $expected_indent + ); + } + + $end_of_previous_item = $end_of_this_item; + continue; + } + + $found_spaces_on_line2 = $this->get_indentation_size( $first_content_on_line2 ); + $expected_spaces_on_line2 = $expected_spaces; + + if ( $found_spaces < $found_spaces_on_line2 ) { + $expected_spaces_on_line2 += ( $found_spaces_on_line2 - $found_spaces ); + } + + if ( $found_spaces_on_line2 !== $expected_spaces_on_line2 ) { + + $fix = $this->phpcsFile->addFixableError( + 'Multi-line array item not aligned correctly; expected %s spaces, but found %s', + $first_content_on_line2, + 'MultiLineArrayItemNotAligned', + array( + $expected_spaces_on_line2, + $found_spaces_on_line2, + ) + ); + + if ( true === $fix ) { + $expected_indent_on_line2 = $this->get_indentation_string( $expected_spaces_on_line2 ); + + $this->phpcsFile->fixer->beginChangeset(); + + // Fix second line for the array item. + if ( 1 === $this->tokens[ $first_content_on_line2 ]['column'] + && \T_COMMENT === $this->tokens[ $first_content_on_line2 ]['code'] + ) { + $actual_comment = ltrim( $this->tokens[ $first_content_on_line2 ]['content'] ); + $replacement = $expected_indent_on_line2 . $actual_comment; + + $this->phpcsFile->fixer->replaceToken( $first_content_on_line2, $replacement ); + + } else { + $this->fix_alignment_error( $first_content_on_line2, $expected_indent_on_line2 ); + } + + // Fix subsequent lines. + for ( $i = ( $first_content_on_line2 + 1 ); $i <= $item['end']; $i++ ) { + // We're only interested in the first token on each line. + if ( 1 !== $this->tokens[ $i ]['column'] ) { + if ( $this->tokens[ $i ]['line'] === $this->tokens[ $item['end'] ]['line'] ) { + // We might as well quit if we're past the first token on the last line. + break; + } + continue; + } + + $first_content_on_line = $this->phpcsFile->findNext( + array( \T_WHITESPACE, \T_DOC_COMMENT_WHITESPACE ), + $i, + $end_of_this_item, + true + ); + + if ( false === $first_content_on_line ) { + break; + } + + // Ignore lines with heredoc and nowdoc tokens and subsequent lines in multi-line strings. + if ( true === $this->ignore_token( $first_content_on_line ) ) { + $i = $first_content_on_line; + continue; + } + + $found_spaces_on_line = $this->get_indentation_size( $first_content_on_line ); + $expected_spaces_on_line = ( $expected_spaces_on_line2 + ( $found_spaces_on_line - $found_spaces_on_line2 ) ); + $expected_spaces_on_line = max( $expected_spaces_on_line, 0 ); // Can't be below 0. + $expected_indent_on_line = $this->get_indentation_string( $expected_spaces_on_line ); + + if ( $found_spaces_on_line !== $expected_spaces_on_line ) { + if ( 1 === $this->tokens[ $first_content_on_line ]['column'] + && \T_COMMENT === $this->tokens[ $first_content_on_line ]['code'] + ) { + $actual_comment = ltrim( $this->tokens[ $first_content_on_line ]['content'] ); + $replacement = $expected_indent_on_line . $actual_comment; + + $this->phpcsFile->fixer->replaceToken( $first_content_on_line, $replacement ); + } else { + $this->fix_alignment_error( $first_content_on_line, $expected_indent_on_line ); + } + } + + // Move past any potential empty lines between the previous non-empty line and this one. + // No need to do the fixes twice. + $i = $first_content_on_line; + } + + /* + * Check the placement of the comma after the array item as it might be on a line by itself. + */ + if ( $this->tokens[ $item['end'] ]['line'] !== $this->tokens[ $end_of_this_item ]['line'] + && \T_COMMA === $this->tokens[ $end_of_this_item ]['code'] + && ( $this->tokens[ $end_of_this_item ]['column'] - 1 ) !== $expected_spaces + ) { + $this->add_array_alignment_error( + $end_of_this_item, + 'Comma after array item not aligned correctly; expected %s spaces, but found %s', + 'MultiLineArrayItemCommaNotAligned', + $expected_spaces, + ( $this->tokens[ $end_of_this_item ]['column'] - 1 ), + $expected_indent + ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + + $end_of_previous_item = $end_of_this_item; + } + } + + /** + * Should the token be ignored ? + * + * This method is only intended to be used with the first token on a line + * for subsequent lines in an multi-line array item. + * + * @param int $ptr Stack pointer to the first token on a line. + * + * @return bool + */ + protected function ignore_token( $ptr ) { + $token_code = $this->tokens[ $ptr ]['code']; + + if ( isset( $this->ignore_tokens[ $token_code ] ) ) { + return true; + } + + /* + * If it's a subsequent line of a multi-line sting, it will not start with a quote + * character, nor just *be* a quote character. + */ + if ( \T_CONSTANT_ENCAPSED_STRING === $token_code + || \T_DOUBLE_QUOTED_STRING === $token_code + ) { + // Deal with closing quote of a multi-line string being on its own line. + if ( "'" === $this->tokens[ $ptr ]['content'] + || '"' === $this->tokens[ $ptr ]['content'] + ) { + return true; + } + + // Deal with subsequent lines of a multi-line string where the token is broken up per line. + if ( "'" !== $this->tokens[ $ptr ]['content'][0] + && '"' !== $this->tokens[ $ptr ]['content'][0] + ) { + return true; + } + } + + return false; + } + + /** + * Determine the line indentation whitespace. + * + * @param int $ptr Stack pointer to an arbitrary token on a line. + * + * @return int Nr of spaces found. Where necessary, tabs are translated to spaces. + */ + protected function get_indentation_size( $ptr ) { + + // Find the first token on the line. + for ( ; $ptr >= 0; $ptr-- ) { + if ( 1 === $this->tokens[ $ptr ]['column'] ) { + break; + } + } + + $whitespace = ''; + + if ( \T_WHITESPACE === $this->tokens[ $ptr ]['code'] + || \T_DOC_COMMENT_WHITESPACE === $this->tokens[ $ptr ]['code'] + ) { + return $this->tokens[ $ptr ]['length']; + } + + /* + * Special case for multi-line, non-docblock comments. + * Only applicable for subsequent lines in an array item. + * + * First/Single line is tokenized as T_WHITESPACE + T_COMMENT + * Subsequent lines are tokenized as T_COMMENT including the indentation whitespace. + */ + if ( \T_COMMENT === $this->tokens[ $ptr ]['code'] ) { + $content = $this->tokens[ $ptr ]['content']; + $actual_comment = ltrim( $content ); + $whitespace = str_replace( $actual_comment, '', $content ); + } + + return \strlen( $whitespace ); + } + + /** + * Create an indentation string. + * + * @param int $nr Number of spaces the indentation should be. + * + * @return string + */ + protected function get_indentation_string( $nr ) { + if ( 0 >= $nr ) { + return ''; + } + + // Space-based indentation. + if ( false === $this->tabIndent ) { + return str_repeat( ' ', $nr ); + } + + // Tab-based indentation. + $num_tabs = (int) floor( $nr / $this->tab_width ); + $remaining = ( $nr % $this->tab_width ); + $tab_indent = str_repeat( "\t", $num_tabs ); + $tab_indent .= str_repeat( ' ', $remaining ); + + return $tab_indent; + } + + /** + * Throw an error and fix incorrect array alignment. + * + * @param int $ptr Stack pointer to the first content on the line. + * @param string $error Error message. + * @param string $error_code Error code. + * @param int $expected Expected nr of spaces (tabs translated to space value). + * @param int $found Found nr of spaces (tabs translated to space value). + * @param string $new_indent Whitespace indent replacement content. + */ + protected function add_array_alignment_error( $ptr, $error, $error_code, $expected, $found, $new_indent ) { + + $fix = $this->phpcsFile->addFixableError( $error, $ptr, $error_code, array( $expected, $found ) ); + if ( true === $fix ) { + $this->fix_alignment_error( $ptr, $new_indent ); + } + } + + /** + * Fix incorrect array alignment. + * + * @param int $ptr Stack pointer to the first content on the line. + * @param string $new_indent Whitespace indent replacement content. + */ + protected function fix_alignment_error( $ptr, $new_indent ) { + if ( 1 === $this->tokens[ $ptr ]['column'] ) { + $this->phpcsFile->fixer->addContentBefore( $ptr, $new_indent ); + } else { + $this->phpcsFile->fixer->replaceToken( ( $ptr - 1 ), $new_indent ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php new file mode 100644 index 000000000..6b3203cd6 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/ArrayKeySpacingRestrictionsSniff.php @@ -0,0 +1,192 @@ +tokens[ $stackPtr ]; + if ( ! isset( $token['bracket_closer'] ) ) { + $this->phpcsFile->addWarning( 'Missing bracket closer.', $stackPtr, 'MissingBracketCloser' ); + return; + } + + $need_spaces = $this->phpcsFile->findNext( + array( \T_CONSTANT_ENCAPSED_STRING, \T_LNUMBER, \T_WHITESPACE, \T_MINUS ), + ( $stackPtr + 1 ), + $token['bracket_closer'], + true + ); + + $spaced1 = ( \T_WHITESPACE === $this->tokens[ ( $stackPtr + 1 ) ]['code'] ); + $spaced2 = ( \T_WHITESPACE === $this->tokens[ ( $token['bracket_closer'] - 1 ) ]['code'] ); + + // It should have spaces unless if it only has strings or numbers as the key. + if ( false !== $need_spaces + && ( false === $spaced1 || false === $spaced2 ) + ) { + $error = 'Array keys must be surrounded by spaces unless they contain a string or an integer.'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpacesAroundArrayKeys' ); + if ( true === $fix ) { + if ( ! $spaced1 ) { + $this->phpcsFile->fixer->addContentBefore( ( $stackPtr + 1 ), ' ' ); + } + if ( ! $spaced2 ) { + $this->phpcsFile->fixer->addContentBefore( $token['bracket_closer'], ' ' ); + } + } + } elseif ( false === $need_spaces && ( $spaced1 || $spaced2 ) ) { + $error = 'Array keys must NOT be surrounded by spaces if they only contain a string or an integer.'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'SpacesAroundArrayKeys' ); + if ( true === $fix ) { + if ( $spaced1 ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), '' ); + + for ( $i = ( $stackPtr + 2 ); $i < $token['bracket_closer']; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + if ( $spaced2 ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( ( $token['bracket_closer'] - 1 ), '' ); + + for ( $i = ( $token['bracket_closer'] - 2 ); $i > $stackPtr; $i-- ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + } + + // If spaces are needed, check that there is only one space. + if ( false !== $need_spaces && ( $spaced1 || $spaced2 ) ) { + if ( $spaced1 ) { + $ptr = ( $stackPtr + 1 ); + $length = 0; + if ( $this->tokens[ $ptr ]['line'] !== $this->tokens[ ( $ptr + 1 ) ]['line'] ) { + $length = 'newline'; + } else { + $length = $this->tokens[ $ptr ]['length']; + } + + if ( 1 !== $length ) { + $error = 'There should be exactly one space before the array key. Found: %s'; + $data = array( $length ); + $fix = $this->phpcsFile->addFixableError( + $error, + $ptr, + 'TooMuchSpaceBeforeKey', + $data + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( $ptr, ' ' ); + + for ( $i = ( $ptr + 1 ); $i < $token['bracket_closer']; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + } + + if ( $spaced2 ) { + $prev_non_empty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $token['bracket_closer'] - 1 ), null, true ); + $ptr = ( $prev_non_empty + 1 ); + $length = 0; + if ( $this->tokens[ $ptr ]['line'] !== $this->tokens[ $token['bracket_closer'] ]['line'] ) { + $length = 'newline'; + } else { + $length = $this->tokens[ $ptr ]['length']; + } + + if ( 1 !== $length ) { + $error = 'There should be exactly one space after the array key. Found: %s'; + $data = array( $length ); + $fix = $this->phpcsFile->addFixableError( + $error, + $ptr, + 'TooMuchSpaceAfterKey', + $data + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + $this->phpcsFile->fixer->replaceToken( $ptr, ' ' ); + + for ( $i = ( $ptr + 1 ); $i < $token['bracket_closer']; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + } + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php new file mode 100644 index 000000000..902bc670b --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/CommaAfterArrayItemSniff.php @@ -0,0 +1,313 @@ +tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + unset( $array_open_close ); + + // This array is empty, so the below checks aren't necessary. + if ( ( $opener + 1 ) === $closer ) { + return; + } + + $single_line = true; + if ( $this->tokens[ $opener ]['line'] !== $this->tokens[ $closer ]['line'] ) { + $single_line = false; + } + + $array_items = $this->get_function_call_parameters( $stackPtr ); + if ( empty( $array_items ) ) { + // Strange, no array items found. + return; + } + + $array_item_count = \count( $array_items ); + + // Note: $item_index is 1-based and the array items are split on the commas! + foreach ( $array_items as $item_index => $item ) { + $maybe_comma = ( $item['end'] + 1 ); + $is_comma = false; + if ( isset( $this->tokens[ $maybe_comma ] ) && \T_COMMA === $this->tokens[ $maybe_comma ]['code'] ) { + $is_comma = true; + } + + /* + * Check if this is a comma at the end of the last item in a single line array. + */ + if ( true === $single_line && $item_index === $array_item_count ) { + + $this->phpcsFile->recordMetric( + $stackPtr, + 'Single line array - comma after last item', + ( true === $is_comma ? 'yes' : 'no' ) + ); + + if ( true === $is_comma ) { + $fix = $this->phpcsFile->addFixableError( + 'Comma not allowed after last value in single-line array declaration', + $maybe_comma, + 'CommaAfterLast' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $maybe_comma, '' ); + } + } + + /* + * No need to do the spacing checks for the last item in a single line array. + * This is handled by another sniff checking the spacing before the array closer. + */ + continue; + } + + $last_content = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + $item['end'], + $item['start'], + true + ); + + if ( false === $last_content ) { + // Shouldn't be able to happen, but just in case, ignore this array item. + continue; + } + + /** + * Make sure every item in a multi-line array has a comma at the end. + * + * Should in reality only be triggered by the last item in a multi-line array + * as otherwise we'd have a parse error already. + */ + if ( false === $is_comma && false === $single_line ) { + + $fix = $this->phpcsFile->addFixableError( + 'Each array item in a multi-line array declaration must end in a comma', + $last_content, + 'NoComma' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $last_content, ',' ); + } + } + + if ( false === $single_line && $item_index === $array_item_count ) { + $this->phpcsFile->recordMetric( + $stackPtr, + 'Multi-line array - comma after last item', + ( true === $is_comma ? 'yes' : 'no' ) + ); + } + + if ( false === $is_comma ) { + // Can't check spacing around the comma if there is no comma. + continue; + } + + /* + * Check for whitespace at the end of the array item. + */ + if ( $last_content !== $item['end'] + // Ignore whitespace at the end of a multi-line item if it is the end of a heredoc/nowdoc. + && ( true === $single_line + || ! isset( Tokens::$heredocTokens[ $this->tokens[ $last_content ]['code'] ] ) ) + ) { + $newlines = 0; + $spaces = 0; + for ( $i = $item['end']; $i > $last_content; $i-- ) { + + if ( \T_WHITESPACE === $this->tokens[ $i ]['code'] ) { + if ( $this->tokens[ $i ]['content'] === $this->phpcsFile->eolChar ) { + $newlines++; + } else { + $spaces += $this->tokens[ $i ]['length']; + } + } elseif ( \T_COMMENT === $this->tokens[ $i ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $i ]['code'] ] ) + ) { + break; + } + } + + $space_phrases = array(); + if ( $spaces > 0 ) { + $space_phrases[] = $spaces . ' spaces'; + } + if ( $newlines > 0 ) { + $space_phrases[] = $newlines . ' newlines'; + } + unset( $newlines, $spaces ); + + $fix = $this->phpcsFile->addFixableError( + 'Expected 0 spaces between "%s" and comma; %s found', + $maybe_comma, + 'SpaceBeforeComma', + array( + $this->tokens[ $last_content ]['content'], + implode( ' and ', $space_phrases ), + ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = $item['end']; $i > $last_content; $i-- ) { + + if ( \T_WHITESPACE === $this->tokens[ $i ]['code'] ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + + } elseif ( \T_COMMENT === $this->tokens[ $i ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $i ]['code'] ] ) + ) { + // We need to move the comma to before the comment. + $this->phpcsFile->fixer->addContent( $last_content, ',' ); + $this->phpcsFile->fixer->replaceToken( $maybe_comma, '' ); + + /* + * No need to worry about removing too much whitespace in + * combination with a `//` comment as in that case, the newline + * is part of the comment, so we're good. + */ + + break; + } + } + $this->phpcsFile->fixer->endChangeset(); + } + } + + if ( ! isset( $this->tokens[ ( $maybe_comma + 1 ) ] ) ) { + // Shouldn't be able to happen, but just in case. + continue; + } + + /* + * Check whitespace after the comma. + */ + $next_token = $this->tokens[ ( $maybe_comma + 1 ) ]; + + if ( \T_WHITESPACE === $next_token['code'] ) { + + if ( false === $single_line && $this->phpcsFile->eolChar === $next_token['content'] ) { + continue; + } + + $next_non_whitespace = $this->phpcsFile->findNext( + \T_WHITESPACE, + ( $maybe_comma + 1 ), + $closer, + true + ); + + if ( false === $next_non_whitespace + || ( false === $single_line + && $this->tokens[ $next_non_whitespace ]['line'] === $this->tokens[ $maybe_comma ]['line'] + && ( \T_COMMENT === $this->tokens[ $next_non_whitespace ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $next_non_whitespace ]['code'] ] ) ) ) + ) { + continue; + } + + $space_length = $next_token['length']; + if ( 1 === $space_length ) { + continue; + } + + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space between comma and "%s"; %s found', + $maybe_comma, + 'SpaceAfterComma', + array( + $this->tokens[ $next_non_whitespace ]['content'], + $space_length, + ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $maybe_comma + 1 ), ' ' ); + } + } else { + // This is either a comment or a mixed single/multi-line array. + // Just add a space and let other sniffs sort out the array layout. + $fix = $this->phpcsFile->addFixableError( + 'Expected 1 space between comma and "%s"; 0 found', + $maybe_comma, + 'NoSpaceAfterComma', + array( $next_token['content'] ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $maybe_comma, ' ' ); + } + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php new file mode 100644 index 000000000..dc68e4f9e --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/MultipleStatementAlignmentSniff.php @@ -0,0 +1,617 @@ += 60, align at column 60. + * - for the outliers, i.e. the array indexes where the end position + * goes past column 60, it will not align the arrow, the sniff will + * just make sure there is only one space between the end of the + * array index and the double arrow. + * + * The column value is regarded as a hard value, i.e. includes indentation, + * so setting it very low is not a good idea. + * + * @since 0.14.0 + * + * @var int + */ + public $maxColumn = 1000; + + /** + * Whether or not to align the arrow operator for multi-line array items. + * + * Whether or not an item is regarded as multi-line is based on the **value** + * of the item, not the key. + * + * Valid values are: + * - 'always': Default. Align all arrays items regardless of single/multi-line. + * - 'never': Never align array items which span multiple lines. + * This will enforce one space between the array index and the + * double arrow operator for multi-line array items, independently + * of the alignment of the rest of the array items. + * Multi-line items where the arrow is already aligned with the + * "expected" alignment, however, will be left alone. + * - operator : Only align the operator for multi-line arrays items if the + * + number percentage of multi-line items passes the comparison. + * - As it is a percentage, the number has to be between 0 and 100. + * - Supported operators: <, <=, >, >=, ==, =, !=, <> + * - The percentage is calculated against all array items + * (with and without assignment operator). + * - The (new) expected alignment will be calculated based only + * on the items being aligned. + * - Multi-line items where the arrow is already aligned with the + * (new) "expected" alignment, however, will be left alone. + * Examples: + * * Setting this to `!=100` or `<100` means that alignment will + * be enforced, unless *all* array items are multi-line. + * This is probably the most commonly desired situation. + * * Setting this to `=100` means that alignment will only + * be enforced, if *all* array items are multi-line. + * * Setting this to `<50` means that the majority of array items + * need to be single line before alignment is enforced for + * multi-line items in the array. + * * Setting this to `=0` is useless as in that case there are + * no multi-line items in the array anyway. + * + * This setting will respect the `ignoreNewlines` and `maxColumnn` settings. + * + * @since 0.14.0 + * + * @var string|int + */ + public $alignMultilineItems = 'always'; + + /** + * Storage for parsed $alignMultilineItems operator part. + * + * @since 0.14.0 + * + * @var string + */ + private $operator; + + /** + * Storage for parsed $alignMultilineItems numeric part. + * + * Stored as a string as the comparison will be done string based. + * + * @since 0.14.0 + * + * @var string + */ + private $number; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.14.0 + * + * @return array + */ + public function register() { + return array( + \T_ARRAY, + \T_OPEN_SHORT_ARRAY, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + && $this->is_short_list( $stackPtr ) + ) { + // Short list, not short array. + return; + } + + /* + * Determine the array opener & closer. + */ + $array_open_close = $this->find_array_open_close( $stackPtr ); + if ( false === $array_open_close ) { + // Array open/close could not be determined. + return; + } + + $opener = $array_open_close['opener']; + $closer = $array_open_close['closer']; + + $array_items = $this->get_function_call_parameters( $stackPtr ); + if ( empty( $array_items ) ) { + return; + } + + // Pass off to either the single line or multi-line array analysis. + if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) { + return $this->process_single_line_array( $stackPtr, $array_items, $opener, $closer ); + } else { + return $this->process_multi_line_array( $stackPtr, $array_items, $opener, $closer ); + } + } + + /** + * Process a single-line array. + * + * While the WP standard does not allow single line multi-item associative arrays, + * this sniff should function independently of that. + * + * The `WordPress.WhiteSpace.OperatorSpacing` sniff already covers checking that + * there is a space between the array key and the double arrow, but doesn't + * enforce it to be exactly one space for single line arrays. + * That is what this method covers. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $items Info array containing information on each array item. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_single_line_array( $stackPtr, $items, $opener, $closer ) { + /* + * For single line arrays, we don't care about what level the arrow is from. + * Just find and fix them all. + */ + $next_arrow = $this->phpcsFile->findNext( + \T_DOUBLE_ARROW, + ( $opener + 1 ), + $closer + ); + + while ( false !== $next_arrow ) { + if ( \T_WHITESPACE === $this->tokens[ ( $next_arrow - 1 ) ]['code'] ) { + $space_length = $this->tokens[ ( $next_arrow - 1 ) ]['length']; + if ( 1 !== $space_length ) { + $error = 'Expected 1 space between "%s" and double arrow; %s found'; + $data = array( + $this->tokens[ ( $next_arrow - 2 ) ]['content'], + $space_length, + ); + + $fix = $this->phpcsFile->addFixableWarning( $error, $next_arrow, 'SpaceBeforeDoubleArrow', $data ); + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $next_arrow - 1 ), ' ' ); + } + } + } + + // Find the position of the next double arrow. + $next_arrow = $this->phpcsFile->findNext( + \T_DOUBLE_ARROW, + ( $next_arrow + 1 ), + $closer + ); + } + + // Ignore any child-arrays as the double arrows in these will already have been handled. + return ( $closer + 1 ); + } + + /** + * Process a multi-line array. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $items Info array containing information on each array item. + * @param int $opener The position of the array opener. + * @param int $closer The position of the array closer. + * + * @return void + */ + protected function process_multi_line_array( $stackPtr, $items, $opener, $closer ) { + + $this->maxColumn = (int) $this->maxColumn; + $this->validate_align_multiline_items(); + + /* + * Determine what the spacing before the arrow should be. + * + * Will unset any array items without double arrow and with new line whitespace + * if newlines are to be ignored, so the second foreach loop only has to deal + * with items which need attention. + * + * This sniff does not take incorrect indentation of array keys into account. + * That's for the `WordPress.Arrays.ArrayIndentation` sniff to fix. + * If that would affect the alignment, a second (or third) loop of the fixer + * will correct it (again) after the indentation has been fixed. + */ + $index_end_cols = array(); // Keep track of the end column position of index keys. + $double_arrow_cols = array(); // Keep track of arrow column position and count. + $multi_line_count = 0; + $total_items = \count( $items ); + + foreach ( $items as $key => $item ) { + if ( strpos( $item['raw'], '=>' ) === false ) { + // Ignore items without assignment operators. + unset( $items[ $key ] ); + continue; + } + + // Find the position of the first double arrow. + $double_arrow = $this->phpcsFile->findNext( + \T_DOUBLE_ARROW, + $item['start'], + ( $item['end'] + 1 ) + ); + + if ( false === $double_arrow ) { + // Shouldn't happen, just in case. + unset( $items[ $key ] ); + continue; + } + + // Make sure the arrow is for this item and not for a nested array value assignment. + $has_array_opener = $this->phpcsFile->findNext( + $this->register(), + $item['start'], + $double_arrow + ); + + if ( false !== $has_array_opener ) { + // Double arrow is for a nested array. + unset( $items[ $key ] ); + continue; + } + + // Find the end of the array key. + $last_index_token = $this->phpcsFile->findPrevious( + \T_WHITESPACE, + ( $double_arrow - 1 ), + $item['start'], + true + ); + + if ( false === $last_index_token ) { + // Shouldn't happen, but just in case. + unset( $items[ $key ] ); + continue; + } + + if ( true === $this->ignoreNewlines + && $this->tokens[ $last_index_token ]['line'] !== $this->tokens[ $double_arrow ]['line'] + ) { + // Ignore this item as it has a new line between the item key and the double arrow. + unset( $items[ $key ] ); + continue; + } + + $index_end_position = ( $this->tokens[ $last_index_token ]['column'] + ( $this->tokens[ $last_index_token ]['length'] - 1 ) ); + $items[ $key ]['operatorPtr'] = $double_arrow; + $items[ $key ]['last_index_token'] = $last_index_token; + $items[ $key ]['last_index_col'] = $index_end_position; + + if ( $this->tokens[ $last_index_token ]['line'] === $this->tokens[ $item['end'] ]['line'] ) { + $items[ $key ]['single_line'] = true; + } else { + $items[ $key ]['single_line'] = false; + $multi_line_count++; + } + + if ( ( $index_end_position + 2 ) <= $this->maxColumn ) { + $index_end_cols[] = $index_end_position; + } + + if ( ! isset( $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ] ) ) { + $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ] = 1; + } else { + $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ]++; + } + } + unset( $key, $item, $double_arrow, $has_array_opener, $last_index_token ); + + if ( empty( $items ) || empty( $index_end_cols ) ) { + // No actionable array items found. + return; + } + + /* + * Determine whether the operators for multi-line items should be aligned. + */ + if ( 'always' === $this->alignMultilineItems ) { + $alignMultilineItems = true; + } elseif ( 'never' === $this->alignMultilineItems ) { + $alignMultilineItems = false; + } else { + $percentage = (string) round( ( $multi_line_count / $total_items ) * 100, 0 ); + + // Bit hacky, but this is the only comparison function in PHP which allows to + // pass the comparison operator. And hey, it works ;-). + $alignMultilineItems = version_compare( $percentage, $this->number, $this->operator ); + } + + /* + * If necessary, rebuild the $index_end_cols and $double_arrow_cols arrays + * excluding multi-line items. + */ + if ( false === $alignMultilineItems ) { + $select_index_end_cols = array(); + $double_arrow_cols = array(); + + foreach ( $items as $item ) { + if ( false === $item['single_line'] ) { + continue; + } + + if ( ( $item['last_index_col'] + 2 ) <= $this->maxColumn ) { + $select_index_end_cols[] = $item['last_index_col']; + } + + if ( ! isset( $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ] ) ) { + $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ] = 1; + } else { + $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ]++; + } + } + } + + /* + * Determine the expected position of the double arrows. + */ + if ( ! empty( $select_index_end_cols ) ) { + $max_index_width = max( $select_index_end_cols ); + } else { + $max_index_width = max( $index_end_cols ); + } + + $expected_col = ( $max_index_width + 2 ); + + if ( false === $this->exact && ! empty( $double_arrow_cols ) ) { + /* + * If the alignment does not have to be exact, see if a majority + * group of the arrows is already at an acceptable position. + */ + arsort( $double_arrow_cols, \SORT_NUMERIC ); + reset( $double_arrow_cols ); + $count = current( $double_arrow_cols ); + + if ( $count > 1 || ( 1 === $count && \count( $items ) === 1 ) ) { + // Allow for several groups of arrows having the same $count. + $filtered_double_arrow_cols = array_keys( $double_arrow_cols, $count, true ); + + foreach ( $filtered_double_arrow_cols as $col ) { + if ( $col > $expected_col && $col <= $this->maxColumn ) { + $expected_col = $col; + break; + } + } + } + } + unset( $max_index_width, $count, $filtered_double_arrow_cols, $col ); + + /* + * Verify and correct the spacing around the double arrows. + */ + foreach ( $items as $item ) { + if ( $this->tokens[ $item['operatorPtr'] ]['column'] === $expected_col + && $this->tokens[ $item['operatorPtr'] ]['line'] === $this->tokens[ $item['last_index_token'] ]['line'] + ) { + // Already correctly aligned. + continue; + } + + if ( \T_WHITESPACE !== $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['code'] ) { + $before = 0; + } else { + if ( $this->tokens[ $item['last_index_token'] ]['line'] !== $this->tokens[ $item['operatorPtr'] ]['line'] ) { + $before = 'newline'; + } else { + $before = $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['length']; + } + } + + /* + * Deal with index sizes larger than maxColumn and with multi-line + * array items which should not be aligned. + */ + if ( ( $item['last_index_col'] + 2 ) > $this->maxColumn + || ( false === $alignMultilineItems && false === $item['single_line'] ) + ) { + + if ( ( $item['last_index_col'] + 2 ) === $this->tokens[ $item['operatorPtr'] ]['column'] + && $this->tokens[ $item['operatorPtr'] ]['line'] === $this->tokens[ $item['last_index_token'] ]['line'] + ) { + // MaxColumn/Multi-line item exception, already correctly aligned. + continue; + } + + $prefix = 'LongIndex'; + if ( false === $alignMultilineItems && false === $item['single_line'] ) { + $prefix = 'MultilineItem'; + } + + $error_code = $prefix . 'SpaceBeforeDoubleArrow'; + if ( 0 === $before ) { + $error_code = $prefix . 'NoSpaceBeforeDoubleArrow'; + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Expected 1 space between "%s" and double arrow; %s found.', + $item['operatorPtr'], + $error_code, + array( + $this->tokens[ $item['last_index_token'] ]['content'], + $before, + ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + // Remove whitespace tokens between the end of the index and the arrow, if any. + for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + // Add the correct whitespace. + $this->phpcsFile->fixer->addContent( $item['last_index_token'], ' ' ); + + $this->phpcsFile->fixer->endChangeset(); + } + continue; + } + + /* + * Deal with the space before double arrows in all other cases. + */ + $expected_whitespace = $expected_col - ( $this->tokens[ $item['last_index_token'] ]['column'] + $this->tokens[ $item['last_index_token'] ]['length'] ); + + $fix = $this->phpcsFile->addFixableWarning( + 'Array double arrow not aligned correctly; expected %s space(s) between "%s" and double arrow, but found %s.', + $item['operatorPtr'], + 'DoubleArrowNotAligned', + array( + $expected_whitespace, + $this->tokens[ $item['last_index_token'] ]['content'], + $before, + ) + ); + + if ( true === $fix ) { + if ( 0 === $before || 'newline' === $before ) { + $this->phpcsFile->fixer->beginChangeset(); + + // Remove whitespace tokens between the end of the index and the arrow, if any. + for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + // Add the correct whitespace. + $this->phpcsFile->fixer->addContent( + $item['last_index_token'], + str_repeat( ' ', $expected_whitespace ) + ); + + $this->phpcsFile->fixer->endChangeset(); + } elseif ( $expected_whitespace > $before ) { + // Add to the existing whitespace to prevent replacing tabs with spaces. + // That's the concern of another sniff. + $this->phpcsFile->fixer->addContent( + ( $item['operatorPtr'] - 1 ), + str_repeat( ' ', ( $expected_whitespace - $before ) ) + ); + } else { + // Too much whitespace found. + $this->phpcsFile->fixer->replaceToken( + ( $item['operatorPtr'] - 1 ), + str_repeat( ' ', $expected_whitespace ) + ); + } + } + } + } + + /** + * Validate that a valid value has been received for the alignMultilineItems property. + * + * This message may be thrown more than once if the property is being changed inline in a file. + * + * @since 0.14.0 + */ + protected function validate_align_multiline_items() { + $alignMultilineItems = $this->alignMultilineItems; + + if ( 'always' === $alignMultilineItems || 'never' === $alignMultilineItems ) { + return; + } else { + // Correct for a potentially added % sign. + $alignMultilineItems = rtrim( $alignMultilineItems, '%' ); + + if ( preg_match( '`^([=<>!]{1,2})(100|[0-9]{1,2})$`', $alignMultilineItems, $matches ) > 0 ) { + $operator = $matches[1]; + $number = (int) $matches[2]; + + if ( \in_array( $operator, array( '<', '<=', '>', '>=', '==', '=', '!=', '<>' ), true ) === true + && ( $number >= 0 && $number <= 100 ) + ) { + $this->alignMultilineItems = $alignMultilineItems; + $this->number = (string) $number; + $this->operator = $operator; + return; + } + } + } + + $this->phpcsFile->addError( + 'Invalid property value passed: "%s". The value for the "alignMultilineItems" property for the "WordPress.Arrays.MultipleStatementAlignment" sniff should be either "always", "never" or an comparison operator + a number between 0 and 100.', + 0, + 'InvalidPropertyPassed', + array( $this->alignMultilineItems ) + ); + + // Reset to the default if an invalid value was received. + $this->alignMultilineItems = 'always'; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php new file mode 100644 index 000000000..3572fbeed --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Classes/ClassInstantiationSniff.php @@ -0,0 +1,204 @@ +classname_tokens = Tokens::$emptyTokens; + $this->classname_tokens[ \T_NS_SEPARATOR ] = \T_NS_SEPARATOR; + $this->classname_tokens[ \T_STRING ] = \T_STRING; + $this->classname_tokens[ \T_SELF ] = \T_SELF; + $this->classname_tokens[ \T_STATIC ] = \T_STATIC; + $this->classname_tokens[ \T_PARENT ] = \T_PARENT; + $this->classname_tokens[ \T_ANON_CLASS ] = \T_ANON_CLASS; + + // Classname in a variable. + $this->classname_tokens[ \T_VARIABLE ] = \T_VARIABLE; + $this->classname_tokens[ \T_DOUBLE_COLON ] = \T_DOUBLE_COLON; + $this->classname_tokens[ \T_OBJECT_OPERATOR ] = \T_OBJECT_OPERATOR; + $this->classname_tokens[ \T_OPEN_SQUARE_BRACKET ] = \T_OPEN_SQUARE_BRACKET; + $this->classname_tokens[ \T_CLOSE_SQUARE_BRACKET ] = \T_CLOSE_SQUARE_BRACKET; + $this->classname_tokens[ \T_CONSTANT_ENCAPSED_STRING ] = \T_CONSTANT_ENCAPSED_STRING; + $this->classname_tokens[ \T_LNUMBER ] = \T_LNUMBER; + + return array( + \T_NEW, + \T_STRING, // JS. + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + // Make sure we have the right token, JS vs PHP. + if ( ( 'PHP' === $this->phpcsFile->tokenizerType && \T_NEW !== $this->tokens[ $stackPtr ]['code'] ) + || ( 'JS' === $this->phpcsFile->tokenizerType + && ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] + || 'new' !== strtolower( $this->tokens[ $stackPtr ]['content'] ) ) ) + ) { + return; + } + + /* + * Check for new by reference used in PHP files. + */ + if ( 'PHP' === $this->phpcsFile->tokenizerType ) { + $prev_non_empty = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false !== $prev_non_empty && 'T_BITWISE_AND' === $this->tokens[ $prev_non_empty ]['type'] ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Assigning new by reference', 'yes' ); + + $this->phpcsFile->addError( + 'Assigning the return value of new by reference is no longer supported by PHP.', + $stackPtr, + 'NewByReferenceFound' + ); + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Assigning new by reference', 'no' ); + } + } + + /* + * Check for parenthesis & correct placement thereof. + */ + $next_non_empty_after_class_name = $this->phpcsFile->findNext( + $this->classname_tokens, + ( $stackPtr + 1 ), + null, + true, + null, + true + ); + + if ( false === $next_non_empty_after_class_name ) { + // Live coding. + return; + } + + // Walk back to the last part of the class name. + $has_comment = false; + for ( $classname_ptr = ( $next_non_empty_after_class_name - 1 ); $classname_ptr >= $stackPtr; $classname_ptr-- ) { + if ( ! isset( Tokens::$emptyTokens[ $this->tokens[ $classname_ptr ]['code'] ] ) ) { + // Prevent a false positive on variable variables, disregard them for now. + if ( $stackPtr === $classname_ptr ) { + return; + } + + break; + } + + if ( \T_WHITESPACE !== $this->tokens[ $classname_ptr ]['code'] ) { + $has_comment = true; + } + } + + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $next_non_empty_after_class_name ]['code'] ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Object instantiation with parenthesis', 'no' ); + + $fix = $this->phpcsFile->addFixableError( + 'Parenthesis should always be used when instantiating a new object.', + $classname_ptr, + 'MissingParenthesis' + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $classname_ptr, '()' ); + } + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Object instantiation with parenthesis', 'yes' ); + + if ( ( $next_non_empty_after_class_name - 1 ) !== $classname_ptr ) { + $this->phpcsFile->recordMetric( + $stackPtr, + 'Space between classname and parenthesis', + ( $next_non_empty_after_class_name - $classname_ptr ) + ); + + $error = 'There must be no spaces between the class name and the open parenthesis when instantiating a new object.'; + $error_code = 'SpaceBeforeParenthesis'; + + if ( false === $has_comment ) { + $fix = $this->phpcsFile->addFixableError( $error, $next_non_empty_after_class_name, $error_code ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = ( $next_non_empty_after_class_name - 1 ); $i > $classname_ptr; $i-- ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + } + } else { + $this->phpcsFile->addError( $error, $next_non_empty_after_class_name, $error_code ); + } + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Space between classname and parenthesis', 0 ); + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php new file mode 100644 index 000000000..bf5879b8d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php @@ -0,0 +1,235 @@ +assignment_tokens = Tokens::$assignmentTokens; + unset( $this->assignment_tokens[ \T_DOUBLE_ARROW ] ); + + $starters = Tokens::$booleanOperators; + $starters[ \T_SEMICOLON ] = \T_SEMICOLON; + $starters[ \T_OPEN_PARENTHESIS ] = \T_OPEN_PARENTHESIS; + $starters[ \T_INLINE_ELSE ] = \T_INLINE_ELSE; + + $this->condition_start_tokens = $starters; + + return array( + \T_IF, + \T_ELSEIF, + \T_FOR, + \T_SWITCH, + \T_CASE, + \T_WHILE, + \T_INLINE_THEN, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + + // Find the condition opener/closer. + if ( \T_FOR === $token['code'] ) { + if ( isset( $token['parenthesis_opener'], $token['parenthesis_closer'] ) === false ) { + return; + } + + $semicolon = $this->phpcsFile->findNext( \T_SEMICOLON, ( $token['parenthesis_opener'] + 1 ), $token['parenthesis_closer'] ); + if ( false === $semicolon ) { + return; + } + + $opener = $semicolon; + $semicolon = $this->phpcsFile->findNext( \T_SEMICOLON, ( $opener + 1 ), $token['parenthesis_closer'] ); + if ( false === $semicolon ) { + return; + } + + $closer = $semicolon; + unset( $semicolon ); + + } elseif ( \T_CASE === $token['code'] ) { + if ( isset( $token['scope_opener'] ) === false ) { + return; + } + + $opener = $stackPtr; + $closer = $token['scope_opener']; + + } elseif ( \T_INLINE_THEN === $token['code'] ) { + // Check if the condition for the ternary is bracketed. + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false === $prev ) { + // Shouldn't happen, but in that case we don't have anything to examine anyway. + return; + } + + if ( \T_CLOSE_PARENTHESIS === $this->tokens[ $prev ]['code'] ) { + if ( ! isset( $this->tokens[ $prev ]['parenthesis_opener'] ) ) { + return; + } + + $opener = $this->tokens[ $prev ]['parenthesis_opener']; + $closer = $prev; + } elseif ( isset( $token['nested_parenthesis'] ) ) { + $closer = end( $token['nested_parenthesis'] ); + $opener = key( $token['nested_parenthesis'] ); + + $next_statement_closer = $this->phpcsFile->findEndOfStatement( $stackPtr, array( \T_COLON, \T_CLOSE_PARENTHESIS, \T_CLOSE_SQUARE_BRACKET ) ); + if ( false !== $next_statement_closer && $next_statement_closer < $closer ) { + // Parentheses are unrelated to the ternary. + return; + } + + $prev_statement_closer = $this->phpcsFile->findStartOfStatement( $stackPtr, array( \T_COLON, \T_OPEN_PARENTHESIS, \T_OPEN_SQUARE_BRACKET ) ); + if ( false !== $prev_statement_closer && $opener < $prev_statement_closer ) { + // Parentheses are unrelated to the ternary. + return; + } + + if ( $closer > $stackPtr ) { + $closer = $stackPtr; + } + } else { + // No parenthesis found, can't determine where the conditional part of the ternary starts. + return; + } + } else { + if ( isset( $token['parenthesis_opener'], $token['parenthesis_closer'] ) === false ) { + return; + } + + $opener = $token['parenthesis_opener']; + $closer = $token['parenthesis_closer']; + } + + $startPos = $opener; + + do { + $hasAssignment = $this->phpcsFile->findNext( $this->assignment_tokens, ( $startPos + 1 ), $closer ); + if ( false === $hasAssignment ) { + return; + } + + // Examine whether the left side is a variable. + $hasVariable = false; + $conditionStart = $startPos; + $altConditionStart = $this->phpcsFile->findPrevious( + $this->condition_start_tokens, + ( $hasAssignment - 1 ), + $startPos + ); + if ( false !== $altConditionStart ) { + $conditionStart = $altConditionStart; + } + + for ( $i = $hasAssignment; $i > $conditionStart; $i-- ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] + || \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $i ]['code'] + ) { + $hasVariable = true; + break; + } + + // If this is a function call or something, we are OK. + if ( \T_CLOSE_PARENTHESIS === $this->tokens[ $i ]['code'] ) { + break; + } + } + + if ( true === $hasVariable ) { + $errorCode = 'Found'; + if ( \T_WHILE === $token['code'] ) { + $errorCode = 'FoundInWhileCondition'; + } elseif ( \T_INLINE_THEN === $token['code'] ) { + $errorCode = 'FoundInTernaryCondition'; + } + + $this->phpcsFile->addWarning( + 'Variable assignment found within a condition. Did you mean to do a comparison?', + $hasAssignment, + $errorCode + ); + } else { + $this->phpcsFile->addWarning( + 'Assignment found within a condition. Did you mean to do a comparison?', + $hasAssignment, + 'NonVariableAssignmentFound' + ); + } + + $startPos = $hasAssignment; + + } while ( $startPos < $closer ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php new file mode 100644 index 000000000..21e220146 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EmptyStatementSniff.php @@ -0,0 +1,161 @@ +tokens[ $stackPtr ]['type'] ) { + /* + * Detect `something();;`. + */ + case 'T_SEMICOLON': + $prevNonEmpty = $this->phpcsFile->findPrevious( + Tokens::$emptyTokens, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false === $prevNonEmpty + || ( \T_SEMICOLON !== $this->tokens[ $prevNonEmpty ]['code'] + && \T_OPEN_TAG !== $this->tokens[ $prevNonEmpty ]['code'] + && \T_OPEN_TAG_WITH_ECHO !== $this->tokens[ $prevNonEmpty ]['code'] ) + ) { + return; + } + + if ( isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + $nested = $this->tokens[ $stackPtr ]['nested_parenthesis']; + $last_closer = array_pop( $nested ); + if ( isset( $this->tokens[ $last_closer ]['parenthesis_owner'] ) + && \T_FOR === $this->tokens[ $this->tokens[ $last_closer ]['parenthesis_owner'] ]['code'] + ) { + // Empty for() condition. + return; + } + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Empty PHP statement detected: superfluous semi-colon.', + $stackPtr, + 'SemicolonWithoutCodeDetected' + ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + if ( \T_OPEN_TAG === $this->tokens[ $prevNonEmpty ]['code'] + || \T_OPEN_TAG_WITH_ECHO === $this->tokens[ $prevNonEmpty ]['code'] + ) { + /* + * Check for superfluous whitespace after the semi-colon which will be + * removed as the `tokens[ ( $stackPtr + 1 ) ]['code'] ) { + $replacement = str_replace( ' ', '', $this->tokens[ ( $stackPtr + 1 ) ]['content'] ); + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), $replacement ); + } + } + + for ( $i = $stackPtr; $i > $prevNonEmpty; $i-- ) { + if ( \T_SEMICOLON !== $this->tokens[ $i ]['code'] + && \T_WHITESPACE !== $this->tokens[ $i ]['code'] + ) { + break; + } + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + break; + + /* + * Detect ``. + */ + case 'T_CLOSE_TAG': + $prevNonEmpty = $this->phpcsFile->findPrevious( + \T_WHITESPACE, + ( $stackPtr - 1 ), + null, + true + ); + + if ( false === $prevNonEmpty + || ( \T_OPEN_TAG !== $this->tokens[ $prevNonEmpty ]['code'] + && \T_OPEN_TAG_WITH_ECHO !== $this->tokens[ $prevNonEmpty ]['code'] ) + ) { + return; + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Empty PHP open/close tag combination detected.', + $prevNonEmpty, + 'EmptyPHPOpenCloseTagsDetected' + ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = $prevNonEmpty; $i <= $stackPtr; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + } + break; + + default: + /* Deliberately left empty. */ + break; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php new file mode 100644 index 000000000..5a7af8774 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/CodeAnalysis/EscapedNotTranslatedSniff.php @@ -0,0 +1,90 @@ + => + */ + protected $target_functions = array( + 'esc_html' => 'esc_html__', + 'esc_attr' => 'esc_attr__', + ); + + /** + * Process the parameters of a matched function. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( \count( $parameters ) === 1 ) { + return; + } + + /* + * We already know that there will be a valid open+close parenthesis, otherwise the sniff + * would have bowed out long before. + */ + $opener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + + $data = array( + $matched_content, + $this->target_functions[ $matched_content ], + $this->phpcsFile->getTokensAsString( $stackPtr, ( $closer - $stackPtr + 1 ) ), + ); + + $this->phpcsFile->addWarning( + '%s() expects only one parameter. Did you mean to use %s() ? Found: %s', + $stackPtr, + 'Found', + $data + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php new file mode 100644 index 000000000..583e9d9c5 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/DirectDatabaseQuerySniff.php @@ -0,0 +1,265 @@ + array(), + 'cacheset' => array(), + 'cachedelete' => array(), + ); + + /** + * The lists of $wpdb methods. + * + * @since 0.6.0 + * @since 0.11.0 Changed from static to non-static. + * + * @var array[] + */ + protected $methods = array( + 'cachable' => array( + 'delete' => true, + 'get_var' => true, + 'get_col' => true, + 'get_row' => true, + 'get_results' => true, + 'query' => true, + 'replace' => true, + 'update' => true, + ), + 'noncachable' => array( + 'insert' => true, + ), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_VARIABLE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + // Check for $wpdb variable. + if ( '$wpdb' !== $this->tokens[ $stackPtr ]['content'] ) { + return; + } + + $is_object_call = $this->phpcsFile->findNext( \T_OBJECT_OPERATOR, ( $stackPtr + 1 ), null, false, null, true ); + if ( false === $is_object_call ) { + return; // This is not a call to the wpdb object. + } + + $methodPtr = $this->phpcsFile->findNext( array( \T_WHITESPACE ), ( $is_object_call + 1 ), null, true, null, true ); + $method = $this->tokens[ $methodPtr ]['content']; + + $this->mergeFunctionLists(); + + if ( ! isset( $this->methods['all'][ $method ] ) ) { + return; + } + + $endOfStatement = $this->phpcsFile->findNext( \T_SEMICOLON, ( $stackPtr + 1 ), null, false, null, true ); + $endOfLineComment = ''; + for ( $i = ( $endOfStatement + 1 ); $i < $this->phpcsFile->numTokens; $i++ ) { + + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $endOfStatement ]['line'] ) { + break; + } + + if ( \T_COMMENT === $this->tokens[ $i ]['code'] ) { + $endOfLineComment .= $this->tokens[ $i ]['content']; + } + } + + $whitelisted_db_call = false; + if ( preg_match( '/db call\W*(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) { + $whitelisted_db_call = true; + } + + // Check for Database Schema Changes. + for ( $_pos = ( $stackPtr + 1 ); $_pos < $endOfStatement; $_pos++ ) { + $_pos = $this->phpcsFile->findNext( Tokens::$textStringTokens, $_pos, $endOfStatement, false, null, true ); + if ( false === $_pos ) { + break; + } + + if ( preg_match( '#\b(?:ALTER|CREATE|DROP)\b#i', $this->tokens[ $_pos ]['content'] ) > 0 ) { + $this->phpcsFile->addWarning( 'Attempting a database schema change is discouraged.', $_pos, 'SchemaChange' ); + } + } + + // Flag instance if not whitelisted. + if ( ! $whitelisted_db_call ) { + $this->phpcsFile->addWarning( 'Usage of a direct database call is discouraged.', $stackPtr, 'DirectQuery' ); + } + + if ( ! isset( $this->methods['cachable'][ $method ] ) ) { + return $endOfStatement; + } + + $whitelisted_cache = false; + $cached = false; + $wp_cache_get = false; + if ( preg_match( '/cache\s+(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) { + $whitelisted_cache = true; + } + if ( ! $whitelisted_cache && ! empty( $this->tokens[ $stackPtr ]['conditions'] ) ) { + $scope_function = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + + if ( false === $scope_function ) { + $scope_function = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + } + + if ( false !== $scope_function ) { + $scopeStart = $this->tokens[ $scope_function ]['scope_opener']; + $scopeEnd = $this->tokens[ $scope_function ]['scope_closer']; + + for ( $i = ( $scopeStart + 1 ); $i < $scopeEnd; $i++ ) { + if ( \T_STRING === $this->tokens[ $i ]['code'] ) { + + if ( isset( $this->cacheDeleteFunctions[ $this->tokens[ $i ]['content'] ] ) ) { + + if ( \in_array( $method, array( 'query', 'update', 'replace', 'delete' ), true ) ) { + $cached = true; + break; + } + } elseif ( isset( $this->cacheGetFunctions[ $this->tokens[ $i ]['content'] ] ) ) { + + $wp_cache_get = true; + + } elseif ( isset( $this->cacheSetFunctions[ $this->tokens[ $i ]['content'] ] ) ) { + + if ( $wp_cache_get ) { + $cached = true; + break; + } + } + } + } + } + } + + if ( ! $cached && ! $whitelisted_cache ) { + $message = 'Direct database call without caching detected. Consider using wp_cache_get() / wp_cache_set() or wp_cache_delete().'; + $this->phpcsFile->addWarning( $message, $stackPtr, 'NoCaching' ); + } + + return $endOfStatement; + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( ! isset( $this->methods['all'] ) ) { + $this->methods['all'] = array_merge( $this->methods['cachable'], $this->methods['noncachable'] ); + } + + if ( $this->customCacheGetFunctions !== $this->addedCustomFunctions['cacheget'] ) { + $this->cacheGetFunctions = $this->merge_custom_array( + $this->customCacheGetFunctions, + $this->cacheGetFunctions + ); + + $this->addedCustomFunctions['cacheget'] = $this->customCacheGetFunctions; + } + + if ( $this->customCacheSetFunctions !== $this->addedCustomFunctions['cacheset'] ) { + $this->cacheSetFunctions = $this->merge_custom_array( + $this->customCacheSetFunctions, + $this->cacheSetFunctions + ); + + $this->addedCustomFunctions['cacheset'] = $this->customCacheSetFunctions; + } + + if ( $this->customCacheDeleteFunctions !== $this->addedCustomFunctions['cachedelete'] ) { + $this->cacheDeleteFunctions = $this->merge_custom_array( + $this->customCacheDeleteFunctions, + $this->cacheDeleteFunctions + ); + + $this->addedCustomFunctions['cachedelete'] = $this->customCacheDeleteFunctions; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php new file mode 100644 index 000000000..8f184c6be --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLPlaceholdersSniff.php @@ -0,0 +1,661 @@ +prepare method. + * + * Check the following issues: + * - The only placeholders supported are: %d, %f (%F) and %s and their variations. + * - Literal % signs need to be properly escaped as `%%`. + * - Simple placeholders (%d, %f, %F, %s) should be left unquoted in the query string. + * - Complex placeholders - numbered and formatted variants - will not be quoted + * automagically by $wpdb->prepare(), so if used for values, should be quoted in + * the query string. + * - Either an array of replacements should be passed matching the number of + * placeholders found or individual parameters for each placeholder should + * be passed. + * - Wildcards for LIKE compare values should be passed in via a replacement parameter. + * + * The sniff allows for a specific pattern with a variable number of placeholders + * created using code along the lines of: + * `sprintf( 'query .... IN (%s) ...', implode( ',', array_fill( 0, count( $something ), '%s' ) ) )`. + * + * A "PreparedSQLPlaceholders replacement count" whitelist comment is supported + * specifically to silence the `ReplacementsWrongNumber` and `UnfinishedPrepare` + * error codes. The other error codes are not affected by it. + * + * @link https://developer.wordpress.org/reference/classes/wpdb/prepare/ + * @link https://core.trac.wordpress.org/changeset/41496 + * @link https://core.trac.wordpress.org/changeset/41471 + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.14.0 + */ +class PreparedSQLPlaceholdersSniff extends Sniff { + + /** + * These regexes copied from http://php.net/manual/en/function.sprintf.php#93552 + * and adjusted for limitations in `$wpdb->prepare()`. + * + * Near duplicate of the one used in the WP.I18n sniff, but with fewer types allowed. + * + * Note: The regex delimiters and modifiers are not included to allow this regex to be + * concatenated together with other regex partials. + * + * @since 0.14.0 + * + * @var string + */ + const PREPARE_PLACEHOLDER_REGEX = '(?: + (? true, + ); + + /** + * Storage for the stack pointer to the method call token. + * + * @since 0.14.0 + * + * @var int + */ + protected $methodPtr; + + /** + * Simple regex snippet to recognize and remember quotes. + * + * @since 0.14.0 + * + * @var string + */ + private $regex_quote = '["\']'; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.14.0 + * + * @return array + */ + public function register() { + return array( + \T_VARIABLE, + \T_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + if ( ! $this->is_wpdb_method_call( $stackPtr, $this->target_methods ) ) { + return; + } + + $parameters = $this->get_function_call_parameters( $this->methodPtr ); + if ( empty( $parameters ) ) { + return; + } + + $query = $parameters[1]; + $text_string_tokens_found = false; + $variable_found = false; + $sql_wildcard_found = false; + $total_placeholders = 0; + $total_parameters = \count( $parameters ); + $valid_in_clauses = array( + 'uses_in' => 0, + 'implode_fill' => 0, + 'adjustment_count' => 0, + ); + + for ( $i = $query['start']; $i <= $query['end']; $i++ ) { + // Skip over groups of tokens if they are part of an inline function call. + if ( isset( $skip_from, $skip_to ) && $i >= $skip_from && $i < $skip_to ) { + $i = $skip_to; + continue; + } + + if ( ! isset( Tokens::$textStringTokens[ $this->tokens[ $i ]['code'] ] ) ) { + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] ) { + if ( '$wpdb' !== $this->tokens[ $i ]['content'] ) { + $variable_found = true; + } + continue; + } + + // Detect a specific pattern for variable replacements in combination with `IN`. + if ( \T_STRING === $this->tokens[ $i ]['code'] ) { + + if ( 'sprintf' === strtolower( $this->tokens[ $i ]['content'] ) ) { + $sprintf_parameters = $this->get_function_call_parameters( $i ); + + if ( ! empty( $sprintf_parameters ) ) { + $skip_from = ( $sprintf_parameters[1]['end'] + 1 ); + $last_param = end( $sprintf_parameters ); + $skip_to = ( $last_param['end'] + 1 ); + + $valid_in_clauses['implode_fill'] += $this->analyse_sprintf( $sprintf_parameters ); + $valid_in_clauses['adjustment_count'] += ( \count( $sprintf_parameters ) - 1 ); + } + unset( $sprintf_parameters, $last_param ); + + } elseif ( 'implode' === strtolower( $this->tokens[ $i ]['content'] ) ) { + $prev = $this->phpcsFile->findPrevious( + Tokens::$textStringTokens, + ( $i - 1 ), + $query['start'] + ); + + $prev_content = $this->strip_quotes( $this->tokens[ $prev ]['content'] ); + $regex_quote = $this->get_regex_quote_snippet( $prev_content, $this->tokens[ $prev ]['content'] ); + + // Only examine the implode if preceded by an ` IN (`. + if ( preg_match( '`\s+IN\s*\(\s*(' . $regex_quote . ')?$`i', $prev_content, $match ) > 0 ) { + + if ( isset( $match[1] ) && $regex_quote !== $this->regex_quote ) { + $this->phpcsFile->addError( + 'Dynamic placeholder generation should not have surrounding quotes.', + $i, + 'QuotedDynamicPlaceholderGeneration' + ); + } + + if ( $this->analyse_implode( $i ) === true ) { + ++$valid_in_clauses['uses_in']; + ++$valid_in_clauses['implode_fill']; + + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] + && isset( $this->tokens[ $next ]['parenthesis_closer'] ) + ) { + $skip_from = ( $i + 1 ); + $skip_to = ( $this->tokens[ $next ]['parenthesis_closer'] + 1 ); + } + } + } + unset( $prev, $next, $prev_content, $regex_quote, $match ); + } + } + + continue; + } + + $text_string_tokens_found = true; + $content = $this->tokens[ $i ]['content']; + + $regex_quote = $this->regex_quote; + if ( isset( Tokens::$stringTokens[ $this->tokens[ $i ]['code'] ] ) ) { + $content = $this->strip_quotes( $content ); + $regex_quote = $this->get_regex_quote_snippet( $content, $this->tokens[ $i ]['content'] ); + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $i ]['code'] + || \T_HEREDOC === $this->tokens[ $i ]['code'] + ) { + // Only interested in actual query text, so strip out variables. + $stripped_content = $this->strip_interpolated_variables( $content ); + if ( $stripped_content !== $content ) { + $interpolated_vars = $this->get_interpolated_variables( $content ); + $vars_without_wpdb = array_diff( $interpolated_vars, array( 'wpdb' ) ); + $content = $stripped_content; + + if ( ! empty( $vars_without_wpdb ) ) { + $variable_found = true; + } + } + unset( $stripped_content, $interpolated_vars, $vars_without_wpdb ); + } + + $placeholders = preg_match_all( '`' . self::PREPARE_PLACEHOLDER_REGEX . '`x', $content, $matches ); + if ( $placeholders > 0 ) { + $total_placeholders += $placeholders; + } + + /* + * Analyse the query for incorrect LIKE queries. + * + * - `LIKE %s` is the only correct one. + * - `LIKE '%s'` or `LIKE "%s"` will not be reported here, but in the quote check. + * - Any other `LIKE` statement should be reported, either for using `LIKE` without + * SQL wildcards or for not passing the SQL wildcards via the replacement. + */ + $regex = '`\s+LIKE\s*(?:(' . $regex_quote . ')(?!%s(?:\1|$))(?P.*?)(?:\1|$)|(?:concat\((?![^\)]*%s[^\)]*\))(?P[^\)]*))\))`i'; + if ( preg_match_all( $regex, $content, $matches ) > 0 ) { + $walk = array(); + if ( ! empty( $matches['content'] ) ) { + $matches['content'] = array_filter( $matches['content'] ); + if ( ! empty( $matches['content'] ) ) { + $walk[] = 'content'; + } + } + if ( ! empty( $matches['concat'] ) ) { + $matches['concat'] = array_filter( $matches['concat'] ); + if ( ! empty( $matches['concat'] ) ) { + $walk[] = 'concat'; + } + } + + if ( ! empty( $walk ) ) { + foreach ( $walk as $match_key ) { + foreach ( $matches[ $match_key ] as $index => $match ) { + $data = array( $matches[0][ $index ] ); + + // Both a `%` as well as a `_` are wildcards in SQL. + if ( strpos( $match, '%' ) === false && strpos( $match, '_' ) === false ) { + $this->phpcsFile->addWarning( + 'Unless you are using SQL wildcards, using LIKE is inefficient. Use a straight compare instead. Found: %s.', + $i, + 'LikeWithoutWildcards', + $data + ); + } else { + $sql_wildcard_found = true; + + if ( strpos( $match, '%s' ) === false ) { + $this->phpcsFile->addError( + 'SQL wildcards for a LIKE query should be passed in through a replacement parameter. Found: %s.', + $i, + 'LikeWildcardsInQuery', + $data + ); + } else { + $this->phpcsFile->addError( + 'SQL wildcards for a LIKE query should be passed in through a replacement parameter and the variable part of the replacement should be escaped using "esc_like()". Found: %s.', + $i, + 'LikeWildcardsInQueryWithPlaceholder', + $data + ); + } + } + + /* + * Don't throw `UnescapedLiteral`, `UnsupportedPlaceholder` or `QuotedPlaceholder` + * for this part of the SQL query. + */ + $content = preg_replace( '`' . preg_quote( $match, '`' ) . '`', '', $content, 1 ); + } + } + } + unset( $matches, $index, $match, $data ); + } + + if ( strpos( $content, '%' ) === false ) { + continue; + } + + /* + * Analyse the query for unsupported placeholders. + */ + if ( preg_match_all( self::UNSUPPORTED_PLACEHOLDER_REGEX, $content, $matches ) > 0 ) { + if ( ! empty( $matches[0] ) ) { + foreach ( $matches[0] as $match ) { + if ( '%' === $match ) { + $this->phpcsFile->addError( + 'Found unescaped literal "%%" character.', + $i, + 'UnescapedLiteral', + array( $match ) + ); + } else { + $this->phpcsFile->addError( + 'Unsupported placeholder used in $wpdb->prepare(). Found: "%s".', + $i, + 'UnsupportedPlaceholder', + array( $match ) + ); + } + } + } + unset( $match, $matches ); + } + + /* + * Analyse the query for quoted placeholders. + */ + $regex = '`(' . $regex_quote . ')%[dfFs]\1`'; + if ( preg_match_all( $regex, $content, $matches ) > 0 ) { + if ( ! empty( $matches[0] ) ) { + foreach ( $matches[0] as $match ) { + $this->phpcsFile->addError( + 'Simple placeholders should not be quoted in the query string in $wpdb->prepare(). Found: %s.', + $i, + 'QuotedSimplePlaceholder', + array( $match ) + ); + } + } + unset( $match, $matches ); + } + + /* + * Analyse the query for unquoted complex placeholders. + */ + $regex = '`(? 0 ) { + if ( ! empty( $matches[0] ) ) { + foreach ( $matches[0] as $match ) { + if ( preg_match( '`%[dfFs]`', $match ) !== 1 ) { + $this->phpcsFile->addWarning( + 'Complex placeholders used for values in the query string in $wpdb->prepare() will NOT be quoted automagically. Found: %s.', + $i, + 'UnquotedComplexPlaceholder', + array( $match ) + ); + } + } + } + unset( $match, $matches ); + } + + /* + * Check for an ` IN (%s)` clause. + */ + $found_in = preg_match_all( '`\s+IN\s*\(\s*%s\s*\)`i', $content, $matches ); + if ( $found_in > 0 ) { + $valid_in_clauses['uses_in'] += $found_in; + } + unset( $found_in ); + } + + if ( false === $text_string_tokens_found ) { + // Query string passed in as a variable or function call, nothing to examine. + return; + } + + $count_diff_whitelisted = $this->has_whitelist_comment( + 'PreparedSQLPlaceholders replacement count', + $stackPtr + ); + + if ( 0 === $total_placeholders ) { + if ( 1 === $total_parameters ) { + if ( false === $variable_found && false === $sql_wildcard_found ) { + /* + * Only throw this warning if the PreparedSQL sniff won't throw one about + * variables being found. + * Also don't throw it if we just advised to use a replacement variable to pass a + * string containing an SQL wildcard. + */ + $this->phpcsFile->addWarning( + 'It is not necessary to prepare a query which doesn\'t use variable replacement.', + $i, + 'UnnecessaryPrepare' + ); + } + } elseif ( false === $count_diff_whitelisted && 0 === $valid_in_clauses['uses_in'] ) { + $this->phpcsFile->addWarning( + 'Replacement variables found, but no valid placeholders found in the query.', + $i, + 'UnfinishedPrepare' + ); + } + + return; + } + + if ( 1 === $total_parameters ) { + $this->phpcsFile->addError( + 'Placeholders found in the query passed to $wpdb->prepare(), but no replacements found. Expected %d replacement(s) parameters.', + $stackPtr, + 'MissingReplacements', + array( $total_placeholders ) + ); + return; + } + + if ( true === $count_diff_whitelisted ) { + return; + } + + $replacements = $parameters; + array_shift( $replacements ); // Remove the query. + + // The parameters may have been passed as an array in parameter 2. + if ( isset( $parameters[2] ) && 2 === $total_parameters ) { + $next = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameters[2]['start'], + ( $parameters[2]['end'] + 1 ), + true + ); + + if ( false !== $next + && ( \T_ARRAY === $this->tokens[ $next ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $next ]['code'] ) + ) { + $replacements = $this->get_function_call_parameters( $next ); + } + } + + $total_replacements = \count( $replacements ); + $total_placeholders -= $valid_in_clauses['adjustment_count']; + + // Bow out when `IN` clauses have been used which appear to be correct. + if ( $valid_in_clauses['uses_in'] > 0 + && $valid_in_clauses['uses_in'] === $valid_in_clauses['implode_fill'] + && 1 === $total_replacements + ) { + return; + } + + /* + * Verify that the correct amount of replacements have been passed. + */ + if ( $total_replacements !== $total_placeholders ) { + $this->phpcsFile->addWarning( + 'Incorrect number of replacements passed to $wpdb->prepare(). Found %d replacement parameters, expected %d.', + $stackPtr, + 'ReplacementsWrongNumber', + array( $total_replacements, $total_placeholders ) + ); + } + } + + /** + * Retrieve a regex snippet to recognize and remember quotes based on the quote style + * used in the original string (if any). + * + * This allows for recognizing `"` and `\'` in single quoted strings, + * recognizing `'` and `\"` in double quotes strings and `'` and `"`when the quote + * style is unknown or it is a non-quoted string (heredoc/nowdoc and such). + * + * @since 0.14.0 + * + * @param string $stripped_content Text string content without surrounding quotes. + * @param string $original_content Original content for the same text string. + * + * @return string + */ + protected function get_regex_quote_snippet( $stripped_content, $original_content ) { + $regex_quote = $this->regex_quote; + + if ( $original_content !== $stripped_content ) { + $quote_style = $original_content[0]; + + if ( '"' === $quote_style ) { + $regex_quote = '\\\\"|\''; + } elseif ( "'" === $quote_style ) { + $regex_quote = '"|\\\\\''; + } + } + + return $regex_quote; + } + + /** + * Analyse a sprintf() query wrapper to see if it contains a specific code pattern + * to deal correctly with `IN` queries. + * + * The pattern we are searching for is: + * `sprintf( 'query ....', implode( ',', array_fill( 0, count( $something ), '%s' ) ) )` + * + * @since 0.14.0 + * + * @param array $sprintf_params Parameters details for the sprintf call. + * + * @return int The number of times the pattern was found in the replacements. + */ + protected function analyse_sprintf( $sprintf_params ) { + $found = 0; + + unset( $sprintf_params[1] ); + + foreach ( $sprintf_params as $sprintf_param ) { + if ( strpos( strtolower( $sprintf_param['raw'] ), 'implode' ) === false ) { + continue; + } + + $implode = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $sprintf_param['start'], + $sprintf_param['end'], + true + ); + if ( \T_STRING === $this->tokens[ $implode ]['code'] + && 'implode' === strtolower( $this->tokens[ $implode ]['content'] ) + ) { + if ( $this->analyse_implode( $implode ) === true ) { + ++$found; + } + } + } + + return $found; + } + + /** + * Analyse an implode() function call to see if it contains a specific code pattern + * to dynamically create placeholders. + * + * The pattern we are searching for is: + * `implode( ',', array_fill( 0, count( $something ), '%s' ) )` + * + * This pattern presumes unquoted placeholders! + * + * @since 0.14.0 + * + * @param int $implode_token The stackPtr to the implode function call. + * + * @return bool True if the pattern is found, false otherwise. + */ + protected function analyse_implode( $implode_token ) { + $implode_params = $this->get_function_call_parameters( $implode_token ); + + if ( empty( $implode_params ) || \count( $implode_params ) !== 2 ) { + return false; + } + + if ( preg_match( '`^(["\']), ?\1$`', $implode_params[1]['raw'] ) !== 1 ) { + return false; + } + + if ( strpos( strtolower( $implode_params[2]['raw'] ), 'array_fill' ) === false ) { + return false; + } + + $array_fill = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $implode_params[2]['start'], + $implode_params[2]['end'], + true + ); + + if ( \T_STRING !== $this->tokens[ $array_fill ]['code'] + || 'array_fill' !== strtolower( $this->tokens[ $array_fill ]['content'] ) + ) { + return false; + } + + $array_fill_params = $this->get_function_call_parameters( $array_fill ); + + if ( empty( $array_fill_params ) || \count( $array_fill_params ) !== 3 ) { + return false; + } + + return (bool) preg_match( '`^(["\'])%[dfFs]\1$`', $array_fill_params[3]['raw'] ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php new file mode 100644 index 000000000..1fe2ad96d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/PreparedSQLSniff.php @@ -0,0 +1,210 @@ + true, + 'get_col' => true, + 'get_row' => true, + 'get_results' => true, + 'prepare' => true, + 'query' => true, + ); + + /** + * Tokens that we don't flag when they are found in a $wpdb method call. + * + * @since 0.9.0 + * + * @var array + */ + protected $ignored_tokens = array( + \T_OBJECT_OPERATOR => true, + \T_OPEN_PARENTHESIS => true, + \T_CLOSE_PARENTHESIS => true, + \T_STRING_CONCAT => true, + \T_CONSTANT_ENCAPSED_STRING => true, + \T_OPEN_SQUARE_BRACKET => true, + \T_CLOSE_SQUARE_BRACKET => true, + \T_COMMA => true, + \T_LNUMBER => true, + \T_START_HEREDOC => true, + \T_END_HEREDOC => true, + \T_START_NOWDOC => true, + \T_NOWDOC => true, + \T_END_NOWDOC => true, + \T_INT_CAST => true, + \T_DOUBLE_CAST => true, + \T_BOOL_CAST => true, + \T_NS_SEPARATOR => true, + ); + + /** + * A loop pointer. + * + * It is a property so that we can access it in all of our methods. + * + * @since 0.9.0 + * + * @var int + */ + protected $i; + + /** + * The loop end marker. + * + * It is a property so that we can access it in all of our methods. + * + * @since 0.9.0 + * + * @var int + */ + protected $end; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.8.0 + * + * @return array + */ + public function register() { + + $this->ignored_tokens += Tokens::$emptyTokens; + + return array( + \T_VARIABLE, + \T_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.8.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( ! $this->is_wpdb_method_call( $stackPtr, $this->methods ) ) { + return; + } + + if ( $this->has_whitelist_comment( 'unprepared SQL', $stackPtr ) ) { + return; + } + + for ( $this->i; $this->i < $this->end; $this->i++ ) { + + if ( isset( $this->ignored_tokens[ $this->tokens[ $this->i ]['code'] ] ) ) { + continue; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $this->i ]['code'] + || \T_HEREDOC === $this->tokens[ $this->i ]['code'] + ) { + + $bad_variables = array_filter( + $this->get_interpolated_variables( $this->tokens[ $this->i ]['content'] ), + function ( $symbol ) { + return ( 'wpdb' !== $symbol ); + } + ); + + foreach ( $bad_variables as $bad_variable ) { + $this->phpcsFile->addError( + 'Use placeholders and $wpdb->prepare(); found interpolated variable $%s at %s', + $this->i, + 'InterpolatedNotPrepared', + array( + $bad_variable, + $this->tokens[ $this->i ]['content'], + ) + ); + } + continue; + } + + if ( \T_VARIABLE === $this->tokens[ $this->i ]['code'] ) { + if ( '$wpdb' === $this->tokens[ $this->i ]['content'] ) { + $this->is_wpdb_method_call( $this->i, $this->methods ); + continue; + } + + if ( $this->is_safe_casted( $this->i ) ) { + continue; + } + } + + if ( \T_STRING === $this->tokens[ $this->i ]['code'] ) { + + if ( + isset( $this->SQLEscapingFunctions[ $this->tokens[ $this->i ]['content'] ] ) + || isset( $this->SQLAutoEscapedFunctions[ $this->tokens[ $this->i ]['content'] ] ) + ) { + + // Find the opening parenthesis. + $opening_paren = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $this->i + 1 ), null, true, null, true ); + + if ( false !== $opening_paren + && \T_OPEN_PARENTHESIS === $this->tokens[ $opening_paren ]['code'] + && isset( $this->tokens[ $opening_paren ]['parenthesis_closer'] ) + ) { + // Skip past the end of the function. + $this->i = $this->tokens[ $opening_paren ]['parenthesis_closer']; + continue; + } + } elseif ( isset( $this->formattingFunctions[ $this->tokens[ $this->i ]['content'] ] ) ) { + continue; + } + } + + $this->phpcsFile->addError( + 'Use placeholders and $wpdb->prepare(); found %s', + $this->i, + 'NotPrepared', + array( $this->tokens[ $this->i ]['content'] ) + ); + } + + return $this->end; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php new file mode 100644 index 000000000..5ae13ee57 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedClassesSniff.php @@ -0,0 +1,60 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Avoid direct calls to the database.', + * 'classes' => array( 'PDO', '\Namespace\Classname' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + + 'mysql' => array( + 'type' => 'error', + 'message' => 'Accessing the database directly should be avoided. Please use the $wpdb object and associated functions instead. Found: %s.', + 'classes' => array( + 'mysqli', + 'PDO', + 'PDOStatement', + ), + ), + + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php new file mode 100644 index 000000000..dbab49fec --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/RestrictedFunctionsSniff.php @@ -0,0 +1,66 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + + 'mysql' => array( + 'type' => 'error', + 'message' => 'Accessing the database directly should be avoided. Please use the $wpdb object and associated functions instead. Found: %s.', + 'functions' => array( + 'mysql_*', + 'mysqli_*', + 'mysqlnd_ms_*', + 'mysqlnd_qc_*', + 'mysqlnd_uh_*', + 'mysqlnd_memcache_*', + 'maxdb_*', + ), + 'whitelist' => array( + 'mysql_to_rfc3339' => true, + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php new file mode 100644 index 000000000..4feebdcb6 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DB/SlowDBQuerySniff.php @@ -0,0 +1,86 @@ + array( + 'type' => 'warning', + 'message' => 'Detected usage of %s, possible slow query.', + 'keys' => array( + 'tax_query', + 'meta_query', + 'meta_key', + 'meta_value', + ), + ), + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.10.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( $this->has_whitelist_comment( 'slow query', $stackPtr ) ) { + return; + } elseif ( $this->has_whitelist_comment( 'tax_query', $stackPtr ) ) { + return; + } + + return parent::process_token( $stackPtr ); + } + + /** + * Callback to process each confirmed key, to check value. + * This must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + return true; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php new file mode 100644 index 000000000..180ae240d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/CurrentTimeTimestampSniff.php @@ -0,0 +1,174 @@ + => + */ + protected $target_functions = array( + 'current_time' => true, + ); + + /** + * Process the parameters of a matched function. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + /* + * We already know there will be valid open & close parentheses as otherwise the parameter + * retrieval function call would have returned an empty array, so no additional checks needed. + */ + $open_parens = $this->phpcsFile->findNext( \T_OPEN_PARENTHESIS, $stackPtr ); + $close_parens = $this->tokens[ $open_parens ]['parenthesis_closer']; + + /* + * Check whether the first parameter is a timestamp format. + */ + for ( $i = $parameters[1]['start']; $i <= $parameters[1]['end']; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + if ( isset( Tokens::$textStringTokens[ $this->tokens[ $i ]['code'] ] ) ) { + $content_first = trim( $this->strip_quotes( $this->tokens[ $i ]['content'] ) ); + if ( 'U' !== $content_first && 'timestamp' !== $content_first ) { + // Most likely valid use of current_time(). + return; + } + + continue; + } + + if ( isset( Tokens::$heredocTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + /* + * If we're still here, we've encountered an unexpected token, like a variable or + * function call. Bow out as we can't determine the runtime value. + */ + return; + } + + $gmt_true = false; + + /* + * Check whether the second parameter, $gmt, is a set to `true` or `1`. + */ + if ( isset( $parameters[2] ) ) { + $content_second = ''; + if ( 'true' === $parameters[2]['raw'] || '1' === $parameters[2]['raw'] ) { + $content_second = $parameters[2]['raw']; + $gmt_true = true; + } else { + // Do a more extensive parameter check. + for ( $i = $parameters[2]['start']; $i <= $parameters[2]['end']; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + $content_second .= $this->tokens[ $i ]['content']; + } + + if ( 'true' === $content_second || '1' === $content_second ) { + $gmt_true = true; + } + } + } + + /* + * Non-UTC timestamp requested. + */ + if ( false === $gmt_true ) { + $this->phpcsFile->addWarning( + 'Calling current_time() with a $type of "timestamp" or "U" is strongly discouraged as it will not return a Unix (UTC) timestamp. Please consider using a non-timestamp format or otherwise refactoring this code.', + $stackPtr, + 'Requested' + ); + + return; + } + + /* + * UTC timestamp requested. Should use time() instead. + */ + $has_comment = $this->phpcsFile->findNext( Tokens::$commentTokens, ( $stackPtr + 1 ), ( $close_parens + 1 ) ); + $error = 'Don\'t use current_time() for retrieving a Unix (UTC) timestamp. Use time() instead. Found: %s'; + $error_code = 'RequestedUTC'; + + $code_snippet = "current_time( '" . $content_first . "'"; + if ( isset( $content_second ) ) { + $code_snippet .= ', ' . $content_second; + } + $code_snippet .= ' )'; + + if ( false !== $has_comment ) { + // If there are comments, we don't auto-fix as it would remove those comments. + $this->phpcsFile->addError( $error, $stackPtr, $error_code, array( $code_snippet ) ); + + return; + } + + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, $error_code, array( $code_snippet ) ); + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $stackPtr + 1 ); $i < $close_parens; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->replaceToken( $stackPtr, 'time(' ); + $this->phpcsFile->fixer->endChangeset(); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php new file mode 100644 index 000000000..0da070190 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php @@ -0,0 +1,62 @@ + array( + 'type' => 'error', + 'message' => 'Using %s() and similar isn\'t allowed, instead use WP internal timezone support.', + 'functions' => array( + 'date_default_timezone_set', + ), + ), + + /* + * Use gmdate(), not date(). + * Don't rely on the current PHP time zone as it might have been changed by third party code. + * + * @link https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/ + * @link https://core.trac.wordpress.org/ticket/46438 + * @link https://github.com/WordPress/WordPress-Coding-Standards/issues/1713 + */ + 'date' => array( + 'type' => 'error', + 'message' => '%s() is affected by runtime timezone changes which can cause date/time to be incorrectly displayed. Use gmdate() instead.', + 'functions' => array( + 'date', + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php new file mode 100644 index 000000000..598bc39bd --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Files/FileNameSniff.php @@ -0,0 +1,248 @@ + true, + 'class.wp-scripts.php' => true, + 'class.wp-styles.php' => true, + ); + + /** + * Unit test version of the historical exceptions in WP core. + * + * @since 0.11.0 + * + * @var array + */ + private $unittest_class_exceptions = array( + 'class.wp-dependencies.inc' => true, + 'class.wp-scripts.inc' => true, + 'class.wp-styles.inc' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + if ( \defined( '\PHP_CODESNIFFER_IN_TESTS' ) ) { + $this->class_exceptions = array_merge( $this->class_exceptions, $this->unittest_class_exceptions ); + } + + return array( + \T_OPEN_TAG, + \T_OPEN_TAG_WITH_ECHO, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + // Usage of `strip_quotes` is to ensure `stdin_path` passed by IDEs does not include quotes. + $file = $this->strip_quotes( $this->phpcsFile->getFileName() ); + if ( 'STDIN' === $file ) { + return; + } + + // Respect phpcs:disable comments as long as they are not accompanied by an enable (PHPCS 3.2+). + if ( \defined( '\T_PHPCS_DISABLE' ) && \defined( '\T_PHPCS_ENABLE' ) ) { + $i = -1; + while ( $i = $this->phpcsFile->findNext( \T_PHPCS_DISABLE, ( $i + 1 ) ) ) { + if ( empty( $this->tokens[ $i ]['sniffCodes'] ) + || isset( $this->tokens[ $i ]['sniffCodes']['WordPress'] ) + || isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files'] ) + || isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files.FileName'] ) + ) { + do { + $i = $this->phpcsFile->findNext( \T_PHPCS_ENABLE, ( $i + 1 ) ); + } while ( false !== $i + && ! empty( $this->tokens[ $i ]['sniffCodes'] ) + && ! isset( $this->tokens[ $i ]['sniffCodes']['WordPress'] ) + && ! isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files'] ) + && ! isset( $this->tokens[ $i ]['sniffCodes']['WordPress.Files.FileName'] ) ); + + if ( false === $i ) { + // The entire (rest of the) file is disabled. + return; + } + } + } + } + + $fileName = basename( $file ); + $expected = strtolower( str_replace( '_', '-', $fileName ) ); + + /* + * Generic check for lowercase hyphenated file names. + */ + if ( $fileName !== $expected && ( false === $this->is_theme || 1 !== preg_match( self::THEME_EXCEPTIONS_REGEX, $fileName ) ) ) { + $this->phpcsFile->addError( + 'Filenames should be all lowercase with hyphens as word separators. Expected %s, but found %s.', + 0, + 'NotHyphenatedLowercase', + array( $expected, $fileName ) + ); + } + unset( $expected ); + + /* + * Check files containing a class for the "class-" prefix and that the rest of + * the file name reflects the class name. + */ + if ( true === $this->strict_class_file_names ) { + $has_class = $this->phpcsFile->findNext( \T_CLASS, $stackPtr ); + if ( false !== $has_class && false === $this->is_test_class( $has_class ) ) { + $class_name = $this->phpcsFile->getDeclarationName( $has_class ); + $expected = 'class-' . strtolower( str_replace( '_', '-', $class_name ) ); + + if ( substr( $fileName, 0, -4 ) !== $expected && ! isset( $this->class_exceptions[ $fileName ] ) ) { + $this->phpcsFile->addError( + 'Class file names should be based on the class name with "class-" prepended. Expected %s, but found %s.', + 0, + 'InvalidClassFileName', + array( + $expected . '.php', + $fileName, + ) + ); + } + unset( $expected ); + } + } + + /* + * Check non-class files in "wp-includes" with a "@subpackage Template" tag for a "-template" suffix. + */ + if ( false !== strpos( $file, \DIRECTORY_SEPARATOR . 'wp-includes' . \DIRECTORY_SEPARATOR ) ) { + $subpackage_tag = $this->phpcsFile->findNext( \T_DOC_COMMENT_TAG, $stackPtr, null, false, '@subpackage' ); + if ( false !== $subpackage_tag ) { + $subpackage = $this->phpcsFile->findNext( \T_DOC_COMMENT_STRING, $subpackage_tag ); + if ( false !== $subpackage ) { + $fileName_end = substr( $fileName, -13 ); + $has_class = $this->phpcsFile->findNext( \T_CLASS, $stackPtr ); + + if ( ( 'Template' === trim( $this->tokens[ $subpackage ]['content'] ) + && $this->tokens[ $subpackage_tag ]['line'] === $this->tokens[ $subpackage ]['line'] ) + && ( ( ! \defined( '\PHP_CODESNIFFER_IN_TESTS' ) && '-template.php' !== $fileName_end ) + || ( \defined( '\PHP_CODESNIFFER_IN_TESTS' ) && '-template.inc' !== $fileName_end ) ) + && false === $has_class + ) { + $this->phpcsFile->addError( + 'Files containing template tags should have "-template" appended to the end of the file name. Expected %s, but found %s.', + 0, + 'InvalidTemplateTagFileName', + array( + substr( $fileName, 0, -4 ) . '-template.php', + $fileName, + ) + ); + } + } + } + } + + // Only run this sniff once per file, no need to run it again. + return ( $this->phpcsFile->numTokens + 1 ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php new file mode 100644 index 000000000..8374faf67 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php @@ -0,0 +1,1046 @@ + true, + 'wp' => true, + '_' => true, + 'php' => true, // See #1728, the 'php' prefix is reserved by PHP itself. + ); + + /** + * Target prefixes after validation. + * + * All prefixes are lowercased for case-insensitive compare. + * + * @since 0.12.0 + * + * @var string[] + */ + private $validated_prefixes = array(); + + /** + * Target namespace prefixes after validation with regex indicator. + * + * All prefixes are lowercased for case-insensitive compare. + * If the prefix doesn't already contain a namespace separator, but does contain + * non-word characters, these will have been replaced with regex syntax to allow + * for namespace separators and the `is_regex` indicator will have been set to `true`. + * + * @since 1.2.0 + * + * @var array + */ + private $validated_namespace_prefixes = array(); + + /** + * Cache of previously set prefixes. + * + * Prevents having to do the same prefix validation over and over again. + * + * @since 0.12.0 + * + * @var string[] + */ + private $previous_prefixes = array(); + + /** + * A list of all PHP superglobals with the exception of $GLOBALS which is handled separately. + * + * @since 0.12.0 + * + * @var array + */ + protected $superglobals = array( + '_COOKIE' => true, + '_ENV' => true, + '_GET' => true, + '_FILES' => true, + '_POST' => true, + '_REQUEST' => true, + '_SERVER' => true, + '_SESSION' => true, + ); + + /** + * A list of core hooks that are allowed to be called by plugins and themes. + * + * @since 0.14.0 + * + * @var array + */ + protected $whitelisted_core_hooks = array( + 'widget_title' => true, + 'add_meta_boxes' => true, + ); + + /** + * A list of core constants that are allowed to be defined by plugins and themes. + * + * @since 1.0.0 + * + * Source: {@link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/default-constants.php#L0} + * The constants are listed in the order they are found in the source file + * to make life easier for future updates. + * Only overrulable constants are listed, i.e. those defined within core within + * a `if ( ! defined() ) {}` wrapper. + * + * @var array + */ + protected $whitelisted_core_constants = array( + 'WP_MEMORY_LIMIT' => true, + 'WP_MAX_MEMORY_LIMIT' => true, + 'WP_CONTENT_DIR' => true, + 'WP_DEBUG' => true, + 'WP_DEBUG_DISPLAY' => true, + 'WP_DEBUG_LOG' => true, + 'WP_CACHE' => true, + 'SCRIPT_DEBUG' => true, + 'MEDIA_TRASH' => true, + 'SHORTINIT' => true, + 'WP_CONTENT_URL' => true, + 'WP_PLUGIN_DIR' => true, + 'WP_PLUGIN_URL' => true, + 'PLUGINDIR' => true, + 'WPMU_PLUGIN_DIR' => true, + 'WPMU_PLUGIN_URL' => true, + 'MUPLUGINDIR' => true, + 'COOKIEHASH' => true, + 'USER_COOKIE' => true, + 'PASS_COOKIE' => true, + 'AUTH_COOKIE' => true, + 'SECURE_AUTH_COOKIE' => true, + 'LOGGED_IN_COOKIE' => true, + 'TEST_COOKIE' => true, + 'COOKIEPATH' => true, + 'SITECOOKIEPATH' => true, + 'ADMIN_COOKIE_PATH' => true, + 'PLUGINS_COOKIE_PATH' => true, + 'COOKIE_DOMAIN' => true, + 'RECOVERY_MODE_COOKIE' => true, + 'FORCE_SSL_ADMIN' => true, + 'FORCE_SSL_LOGIN' => true, + 'AUTOSAVE_INTERVAL' => true, + 'EMPTY_TRASH_DAYS' => true, + 'WP_POST_REVISIONS' => true, + 'WP_CRON_LOCK_TIMEOUT' => true, + 'WP_DEFAULT_THEME' => true, + ); + + /** + * List of all PHP native functions. + * + * Using this list rather than a call to `function_exists()` prevents + * false negatives from user-defined functions when those would be + * autoloaded via a Composer autoload files directives. + * + * @var array + */ + private $built_in_functions; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.12.0 + * + * @return array + */ + public function register() { + // Get a list of all PHP native functions. + $all_functions = get_defined_functions(); + $this->built_in_functions = array_flip( $all_functions['internal'] ); + + // Set the sniff targets. + $targets = array( + \T_NAMESPACE => \T_NAMESPACE, + \T_FUNCTION => \T_FUNCTION, + \T_CONST => \T_CONST, + \T_VARIABLE => \T_VARIABLE, + \T_DOLLAR => \T_DOLLAR, // Variable variables. + \T_LIST => \T_LIST, + \T_OPEN_SHORT_ARRAY => \T_OPEN_SHORT_ARRAY, + ); + $targets += Tokens::$ooScopeTokens; // T_ANON_CLASS is only used for skipping over test classes. + + // Add function call target for hook names and constants defined using define(). + $parent = parent::register(); + if ( ! empty( $parent ) ) { + $targets[] = \T_STRING; + } + + return $targets; + } + + /** + * Groups of functions to restrict. + * + * @since 0.12.0 + * + * @return array + */ + public function getGroups() { + $this->target_functions = $this->hookInvokeFunctions; + unset( + $this->target_functions['do_action_deprecated'], + $this->target_functions['apply_filters_deprecated'] + ); + + $this->target_functions['define'] = true; + + return parent::getGroups(); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + /* + * Allow for whitelisting. + * + * Generally speaking a theme/plugin should *only* execute their own hooks, but there may be a + * good reason to execute a core hook. + * + * Similarly, newer PHP or WP functions or constants may need to be emulated for continued support + * of older PHP and WP versions. + */ + if ( $this->has_whitelist_comment( 'prefix', $stackPtr ) ) { + return; + } + + // Allow overruling the prefixes set in a ruleset via the command line. + $cl_prefixes = trim( PHPCSHelper::get_config_data( 'prefixes' ) ); + if ( ! empty( $cl_prefixes ) ) { + $this->prefixes = array_filter( array_map( 'trim', explode( ',', $cl_prefixes ) ) ); + } + + $this->prefixes = $this->merge_custom_array( $this->prefixes, array(), false ); + if ( empty( $this->prefixes ) ) { + // No prefixes passed, nothing to do. + return; + } + + $this->validate_prefixes(); + if ( empty( $this->validated_prefixes ) ) { + // No _valid_ prefixes passed, nothing to do. + return; + } + + // Ignore test classes. + if ( isset( Tokens::$ooScopeTokens[ $this->tokens[ $stackPtr ]['code'] ] ) + && true === $this->is_test_class( $stackPtr ) + ) { + if ( $this->tokens[ $stackPtr ]['scope_condition'] === $stackPtr && isset( $this->tokens[ $stackPtr ]['scope_closer'] ) ) { + // Skip forward to end of test class. + return $this->tokens[ $stackPtr ]['scope_closer']; + } + return; + } + + if ( \T_ANON_CLASS === $this->tokens[ $stackPtr ]['code'] ) { + // Token was only registered to allow skipping over test classes. + return; + } + + if ( \T_STRING === $this->tokens[ $stackPtr ]['code'] ) { + // Disallow excluding function groups for this sniff. + $this->exclude = array(); + + return parent::process_token( $stackPtr ); + + } elseif ( \T_DOLLAR === $this->tokens[ $stackPtr ]['code'] ) { + + return $this->process_variable_variable( $stackPtr ); + + } elseif ( \T_VARIABLE === $this->tokens[ $stackPtr ]['code'] ) { + + return $this->process_variable_assignment( $stackPtr ); + + } elseif ( \T_LIST === $this->tokens[ $stackPtr ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] + ) { + return $this->process_list_assignment( $stackPtr ); + + } elseif ( \T_NAMESPACE === $this->tokens[ $stackPtr ]['code'] ) { + $namespace_name = $this->get_declared_namespace_name( $stackPtr ); + + if ( false === $namespace_name || '' === $namespace_name || '\\' === $namespace_name ) { + return; + } + + foreach ( $this->validated_namespace_prefixes as $key => $prefix_info ) { + if ( false === $prefix_info['is_regex'] ) { + if ( stripos( $namespace_name, $prefix_info['prefix'] ) === 0 ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: allowed prefixes', $key ); + return; + } + } else { + // Ok, so this prefix should be used as a regex. + $regex = '`^' . $prefix_info['prefix'] . '`i'; + if ( preg_match( $regex, $namespace_name ) > 0 ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: allowed prefixes', $key ); + return; + } + } + } + + // Still here ? In that case, we have a non-prefixed namespace name. + $recorded = $this->phpcsFile->addError( + self::ERROR_MSG, + $stackPtr, + 'NonPrefixedNamespaceFound', + array( + 'Namespaces declared', + $namespace_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $namespace_name ); + } + + return; + + } else { + + // Namespaced methods, classes and constants do not need to be prefixed. + $namespace = $this->determine_namespace( $stackPtr ); + if ( '' !== $namespace && '\\' !== $namespace ) { + return; + } + + $item_name = ''; + $error_text = 'Unknown syntax used'; + $error_code = 'NonPrefixedSyntaxFound'; + + switch ( $this->tokens[ $stackPtr ]['type'] ) { + case 'T_FUNCTION': + // Methods in a class do not need to be prefixed. + if ( $this->phpcsFile->hasCondition( $stackPtr, Tokens::$ooScopeTokens ) === true ) { + return; + } + + if ( $this->is_function_deprecated( $this->phpcsFile, $stackPtr ) === true ) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $item_name = $this->phpcsFile->getDeclarationName( $stackPtr ); + if ( isset( $this->built_in_functions[ $item_name ] ) ) { + // Backfill for PHP native function. + return; + } + + $error_text = 'Functions declared in the global namespace'; + $error_code = 'NonPrefixedFunctionFound'; + break; + + case 'T_CLASS': + case 'T_INTERFACE': + case 'T_TRAIT': + $item_name = $this->phpcsFile->getDeclarationName( $stackPtr ); + $error_text = 'Classes declared'; + $error_code = 'NonPrefixedClassFound'; + + switch ( $this->tokens[ $stackPtr ]['type'] ) { + case 'T_CLASS': + if ( class_exists( '\\' . $item_name, false ) ) { + // Backfill for PHP native class. + return; + } + break; + + case 'T_INTERFACE': + if ( interface_exists( '\\' . $item_name, false ) ) { + // Backfill for PHP native interface. + return; + } + + $error_text = 'Interfaces declared'; + $error_code = 'NonPrefixedInterfaceFound'; + break; + + case 'T_TRAIT': + // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.trait_existsFound + if ( function_exists( '\trait_exists' ) && trait_exists( '\\' . $item_name, false ) ) { + // Backfill for PHP native trait. + return; + } + + $error_text = 'Traits declared'; + $error_code = 'NonPrefixedTraitFound'; + break; + + default: + // Left empty on purpose. + break; + } + + break; + + case 'T_CONST': + // Constants in a class do not need to be prefixed. + if ( true === $this->is_class_constant( $stackPtr ) ) { + return; + } + + $constant_name_ptr = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false === $constant_name_ptr ) { + // Live coding. + return; + } + + $item_name = $this->tokens[ $constant_name_ptr ]['content']; + if ( \defined( '\\' . $item_name ) ) { + // Backfill for PHP native constant. + return; + } + + if ( isset( $this->whitelisted_core_constants[ $item_name ] ) ) { + // Defining a WP Core constant intended for overruling. + return; + } + + $error_text = 'Global constants defined'; + $error_code = 'NonPrefixedConstantFound'; + break; + + default: + // Left empty on purpose. + break; + + } + + if ( empty( $item_name ) || $this->is_prefixed( $stackPtr, $item_name ) === true ) { + return; + } + + $recorded = $this->phpcsFile->addError( + self::ERROR_MSG, + $stackPtr, + $error_code, + array( + $error_text, + $item_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $item_name ); + } + } + } + + /** + * Handle variable variables defined in the global namespace. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_variable_variable( $stackPtr ) { + static $indicators = array( + \T_OPEN_CURLY_BRACKET => true, + \T_VARIABLE => true, + ); + + // Is this a variable variable ? + // Not concerned with nested ones as those will be recognized on their own token. + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false === $next_non_empty || ! isset( $indicators[ $this->tokens[ $next_non_empty ]['code'] ] ) ) { + return; + } + + if ( \T_OPEN_CURLY_BRACKET === $this->tokens[ $next_non_empty ]['code'] + && isset( $this->tokens[ $next_non_empty ]['bracket_closer'] ) + ) { + // Skip over the variable part. + $next_non_empty = $this->tokens[ $next_non_empty ]['bracket_closer']; + } + + $maybe_assignment = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true, null, true ); + + while ( false !== $maybe_assignment + && \T_OPEN_SQUARE_BRACKET === $this->tokens[ $maybe_assignment ]['code'] + && isset( $this->tokens[ $maybe_assignment ]['bracket_closer'] ) + ) { + $maybe_assignment = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $this->tokens[ $maybe_assignment ]['bracket_closer'] + 1 ), + null, + true, + null, + true + ); + } + + if ( false === $maybe_assignment ) { + return; + } + + if ( ! isset( Tokens::$assignmentTokens[ $this->tokens[ $maybe_assignment ]['code'] ] ) ) { + // Not an assignment. + return; + } + + $error = self::ERROR_MSG; + + /* + * Local variable variables in a function do not need to be prefixed. + * But a variable variable could evaluate to the name of an imported global + * variable. + * Not concerned with imported variable variables (global.. ) as that has been + * forbidden since PHP 7.0. Presuming cross-version code and if not, that + * is for the PHPCompatibility standard to detect. + */ + if ( $this->phpcsFile->hasCondition( $stackPtr, array( \T_FUNCTION, \T_CLOSURE ) ) === true ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + if ( false === $condition ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + } + + $has_global = $this->phpcsFile->findPrevious( \T_GLOBAL, ( $stackPtr - 1 ), $this->tokens[ $condition ]['scope_opener'] ); + if ( false === $has_global ) { + // No variable import happening. + return; + } + + $error = 'Variable variable which could potentially override an imported global variable detected. ' . $error; + } + + $variable_name = $this->phpcsFile->getTokensAsString( $stackPtr, ( ( $next_non_empty - $stackPtr ) + 1 ) ); + + // Still here ? In that case, the variable name should be prefixed. + $recorded = $this->phpcsFile->addWarning( + $error, + $stackPtr, + 'NonPrefixedVariableFound', + array( + 'Global variables defined', + $variable_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $variable_name ); + } + + // Skip over the variable part of the variable. + return ( $next_non_empty + 1 ); + } + + /** + * Check that defined global variables are prefixed. + * + * @since 0.12.0 + * @since 2.2.0 Added $in_list parameter. + * + * @param int $stackPtr The position of the current token in the stack. + * @param bool $in_list Whether or not this is a variable in a list assignment. + * Defaults to false. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_variable_assignment( $stackPtr, $in_list = false ) { + /* + * We're only concerned with variables which are being defined. + * `is_assigment()` will not recognize property assignments, which is good in this case. + * However it will also not recognize $b in `foreach( $a as $b )` as an assignment, so + * we need a separate check for that. + */ + if ( false === $in_list + && false === $this->is_assignment( $stackPtr ) + && false === $this->is_foreach_as( $stackPtr ) + ) { + return; + } + + $is_error = true; + $variable_name = substr( $this->tokens[ $stackPtr ]['content'], 1 ); // Strip the dollar sign. + + // Bow out early if we know for certain no prefix is needed. + if ( $this->variable_prefixed_or_whitelisted( $stackPtr, $variable_name ) === true ) { + return; + } + + if ( 'GLOBALS' === $variable_name ) { + $array_open = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false === $array_open || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $array_open ]['code'] ) { + // Live coding or something very silly. + return; + } + + $array_key = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $array_open + 1 ), null, true, null, true ); + if ( false === $array_key ) { + // No key found, nothing to do. + return; + } + + $stackPtr = $array_key; + $variable_name = $this->strip_quotes( $this->tokens[ $array_key ]['content'] ); + + // Check whether a prefix is needed. + if ( isset( Tokens::$stringTokens[ $this->tokens[ $array_key ]['code'] ] ) + && $this->variable_prefixed_or_whitelisted( $stackPtr, $variable_name ) === true + ) { + return; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $array_key ]['code'] ) { + // If the array key is a double quoted string, try again with only + // the part before the first variable (if any). + $exploded = explode( '$', $variable_name ); + $first = rtrim( $exploded[0], '{' ); + if ( '' !== $first ) { + if ( $this->variable_prefixed_or_whitelisted( $array_key, $first ) === true ) { + return; + } + } else { + // If the first part was dynamic, throw a warning. + $is_error = false; + } + } elseif ( ! isset( Tokens::$stringTokens[ $this->tokens[ $array_key ]['code'] ] ) ) { + // Dynamic array key, throw a warning. + $is_error = false; + } + } else { + // Function parameters do not need to be prefixed. + if ( false === $in_list && isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + foreach ( $this->tokens[ $stackPtr ]['nested_parenthesis'] as $opener => $closer ) { + if ( isset( $this->tokens[ $opener ]['parenthesis_owner'] ) + && ( \T_FUNCTION === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] + || \T_CLOSURE === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] ) + ) { + return; + } + } + unset( $opener, $closer ); + } + + // Properties in a class do not need to be prefixed. + if ( false === $in_list && true === $this->is_class_property( $stackPtr ) ) { + return; + } + + // Local variables in a function do not need to be prefixed unless they are being imported. + if ( $this->phpcsFile->hasCondition( $stackPtr, array( \T_FUNCTION, \T_CLOSURE ) ) === true ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + if ( false === $condition ) { + $condition = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + } + + $has_global = $this->phpcsFile->findPrevious( \T_GLOBAL, ( $stackPtr - 1 ), $this->tokens[ $condition ]['scope_opener'] ); + if ( false === $has_global ) { + // No variable import happening. + return; + } + + // Ok, this may be an imported global variable. + $end_of_statement = $this->phpcsFile->findNext( \T_SEMICOLON, ( $has_global + 1 ) ); + if ( false === $end_of_statement ) { + // No semi-colon - live coding. + return; + } + + for ( $ptr = ( $has_global + 1 ); $ptr <= $end_of_statement; $ptr++ ) { + // Move the stack pointer to the next variable. + $ptr = $this->phpcsFile->findNext( \T_VARIABLE, $ptr, $end_of_statement, false, null, true ); + + if ( false === $ptr ) { + // Reached the end of the global statement without finding the variable, + // so this must be a local variable. + return; + } + + if ( substr( $this->tokens[ $ptr ]['content'], 1 ) === $variable_name ) { + break; + } + } + + unset( $condition, $has_global, $end_of_statement, $ptr, $imported ); + + } + } + + // Still here ? In that case, the variable name should be prefixed. + $recorded = $this->addMessage( + self::ERROR_MSG, + $stackPtr, + $is_error, + 'NonPrefixedVariableFound', + array( + 'Global variables defined', + '$' . $variable_name, + ) + ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $variable_name ); + } + } + + /** + * Check that global variables declared via a list construct are prefixed. + * + * @internal No need to take special measures for nested lists. Nested or not, + * each list part can only contain one variable being written to. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_list_assignment( $stackPtr ) { + $list_open_close = $this->find_list_open_close( $stackPtr ); + if ( false === $list_open_close ) { + // Short array, not short list. + return; + } + + $var_pointers = $this->get_list_variables( $stackPtr, $list_open_close ); + foreach ( $var_pointers as $ptr ) { + $this->process_variable_assignment( $ptr, true ); + } + + // No need to re-examine these variables. + return $list_open_close['closer']; + } + + /** + * Process the parameters of a matched function. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + // No matter whether it is a constant definition or a hook call, both use the first parameter. + if ( ! isset( $parameters[1] ) ) { + return; + } + + $is_error = true; + $raw_content = $this->strip_quotes( $parameters[1]['raw'] ); + + if ( ( 'define' !== $matched_content + && isset( $this->whitelisted_core_hooks[ $raw_content ] ) ) + || ( 'define' === $matched_content + && isset( $this->whitelisted_core_constants[ $raw_content ] ) ) + ) { + return; + } + + if ( $this->is_prefixed( $parameters[1]['start'], $raw_content ) === true ) { + return; + } else { + // This may be a dynamic hook/constant name. + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameters[1]['start'], + ( $parameters[1]['end'] + 1 ), + true + ); + + if ( false === $first_non_empty ) { + return; + } + + $first_non_empty_content = $this->strip_quotes( $this->tokens[ $first_non_empty ]['content'] ); + + // Try again with just the first token if it's a text string. + if ( isset( Tokens::$stringTokens[ $this->tokens[ $first_non_empty ]['code'] ] ) + && $this->is_prefixed( $parameters[1]['start'], $first_non_empty_content ) === true + ) { + return; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $first_non_empty ]['code'] ) { + // If the first part of the parameter is a double quoted string, try again with only + // the part before the first variable (if any). + $exploded = explode( '$', $first_non_empty_content ); + $first = rtrim( $exploded[0], '{' ); + if ( '' !== $first ) { + if ( $this->is_prefixed( $parameters[1]['start'], $first ) === true ) { + return; + } + } else { + // Start of hook/constant name is dynamic, throw a warning. + $is_error = false; + } + } elseif ( ! isset( Tokens::$stringTokens[ $this->tokens[ $first_non_empty ]['code'] ] ) ) { + // Dynamic hook/constant name, throw a warning. + $is_error = false; + } + } + + if ( 'define' === $matched_content ) { + if ( \defined( '\\' . $raw_content ) ) { + // Backfill for PHP native constant. + return; + } + + if ( strpos( $raw_content, '\\' ) !== false ) { + // Namespaced or unreachable constant. + return; + } + + $data = array( 'Global constants defined' ); + $error_code = 'NonPrefixedConstantFound'; + if ( false === $is_error ) { + $error_code = 'VariableConstantNameFound'; + } + } else { + $data = array( 'Hook names invoked' ); + $error_code = 'NonPrefixedHooknameFound'; + if ( false === $is_error ) { + $error_code = 'DynamicHooknameFound'; + } + } + + $data[] = $raw_content; + + $recorded = $this->addMessage( self::ERROR_MSG, $first_non_empty, $is_error, $error_code, $data ); + + if ( true === $recorded ) { + $this->record_potential_prefix_metric( $stackPtr, $raw_content ); + } + } + + /** + * Check if a function/class/constant/variable name is prefixed with one of the expected prefixes. + * + * @since 0.12.0 + * @since 0.14.0 Allows for other non-word characters as well as underscores to better support hook names. + * @since 1.0.0 Does not require a word seperator anymore after a prefix. + * This allows for improved code style independent checking, + * i.e. allows for camelCase naming and the likes. + * @since 1.0.1 - Added $stackPtr parameter. + * - The function now also records metrics about the prefixes encountered. + * + * @param int $stackPtr The position of the token to record the metric against. + * @param string $name Name to check for a prefix. + * + * @return bool True when the name is one of the prefixes or starts with an allowed prefix. + * False otherwise. + */ + private function is_prefixed( $stackPtr, $name ) { + foreach ( $this->validated_prefixes as $prefix ) { + if ( stripos( $name, $prefix ) === 0 ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: allowed prefixes', $prefix ); + return true; + } + } + + return false; + } + + /** + * Check if a variable name might need a prefix. + * + * Prefix is not needed for: + * - superglobals, + * - WP native globals, + * - variables which are already prefixed. + * + * @since 0.12.0 + * @since 1.0.1 Added $stackPtr parameter. + * + * @param int $stackPtr The position of the token to record the metric against. + * @param string $name Variable name without the dollar sign. + * + * @return bool True if the variable name is whitelisted or already prefixed. + * False otherwise. + */ + private function variable_prefixed_or_whitelisted( $stackPtr, $name ) { + // Ignore superglobals and WP global variables. + if ( isset( $this->superglobals[ $name ] ) || isset( $this->wp_globals[ $name ] ) ) { + return true; + } + + return $this->is_prefixed( $stackPtr, $name ); + } + + /** + * Validate an array of prefixes as passed through a custom property or via the command line. + * + * Checks that the prefix: + * - is not one of the blacklisted ones. + * - complies with the PHP rules for valid function, class, variable, constant names. + * + * @since 0.12.0 + */ + private function validate_prefixes() { + if ( $this->previous_prefixes === $this->prefixes ) { + return; + } + + // Set the cache *before* validation so as to not break the above compare. + $this->previous_prefixes = $this->prefixes; + + // Validate the passed prefix(es). + $prefixes = array(); + $ns_prefixes = array(); + foreach ( $this->prefixes as $key => $prefix ) { + $prefixLC = strtolower( $prefix ); + + if ( isset( $this->prefix_blacklist[ $prefixLC ] ) ) { + $this->phpcsFile->addError( + 'The "%s" prefix is not allowed.', + 0, + 'ForbiddenPrefixPassed', + array( $prefix ) + ); + continue; + } + + $prefix_length = strlen( $prefix ); + if ( function_exists( 'iconv_strlen' ) ) { + $prefix_length = iconv_strlen( $prefix, $this->phpcsFile->config->encoding ); + } + + if ( $prefix_length < self::MIN_PREFIX_LENGTH ) { + $this->phpcsFile->addError( + 'The "%s" prefix is too short. Short prefixes are not unique enough and may cause name collisions with other code.', + 0, + 'ShortPrefixPassed', + array( $prefix ) + ); + continue; + } + + // Validate the prefix against characters allowed for function, class, constant names etc. + if ( preg_match( '`^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff\\\\]*$`', $prefix ) !== 1 ) { + $this->phpcsFile->addWarning( + 'The "%s" prefix is not a valid namespace/function/class/variable/constant prefix in PHP.', + 0, + 'InvalidPrefixPassed', + array( $prefix ) + ); + } + + // Lowercase the prefix to allow for direct compare. + $prefixes[ $key ] = $prefixLC; + + /* + * Replace non-word characters in the prefix with a regex snippet, but only if the + * string doesn't already contain namespace separators. + */ + $is_regex = false; + if ( strpos( $prefix, '\\' ) === false && preg_match( '`[_\W]`', $prefix ) > 0 ) { + $prefix = preg_replace( '`([_\W])`', '[\\\\\\\\$1]', $prefixLC ); + $is_regex = true; + } + + $ns_prefixes[ $prefixLC ] = array( + 'prefix' => $prefix, + 'is_regex' => $is_regex, + ); + } + + // Set the validated prefixes caches. + $this->validated_prefixes = $prefixes; + $this->validated_namespace_prefixes = $ns_prefixes; + } + + /** + * Record the "potential prefix" metric. + * + * @since 1.0.1 + * + * @param int $stackPtr The position of the token to record the metric against. + * @param string $construct_name Name of the global construct to try and distill a potential prefix from. + * + * @return void + */ + private function record_potential_prefix_metric( $stackPtr, $construct_name ) { + if ( preg_match( '`^([A-Z]*[a-z0-9]*+)`', ltrim( $construct_name, '\$_' ), $matches ) > 0 + && isset( $matches[1] ) && '' !== $matches[1] + ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: potential prefixes - start of non-prefixed construct', strtolower( $matches[1] ) ); + } + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 000000000..d8826ce1c --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,187 @@ +getDeclarationName( $stackPtr ); + + if ( ! isset( $functionName ) ) { + // Ignore closures. + return; + } + + if ( '' === ltrim( $functionName, '_' ) ) { + // Ignore special functions, like __(). + return; + } + + $functionNameLc = strtolower( $functionName ); + + // Is this a magic function ? I.e., it is prefixed with "__" ? + // Outside class scope this basically just means __autoload(). + if ( 0 === strpos( $functionName, '__' ) ) { + $magicPart = substr( $functionNameLc, 2 ); + if ( isset( $this->magicFunctions[ $magicPart ] ) ) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $errorData = array( $functionName ); + $phpcsFile->addError( $error, $stackPtr, 'FunctionDoubleUnderscore', $errorData ); + } + + if ( $functionNameLc !== $functionName ) { + $error = 'Function name "%s" is not in snake case format, try "%s"'; + $errorData = array( + $functionName, + Sniff::get_snake_case_name_suggestion( $functionName ), + ); + $phpcsFile->addError( $error, $stackPtr, 'FunctionNameInvalid', $errorData ); + } + } + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currScope ) { + + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[ $stackPtr ]['conditions']; + end( $conditions ); + $deepestScope = key( $conditions ); + if ( $deepestScope !== $currScope ) { + return; + } + + if ( Sniff::is_function_deprecated( $phpcsFile, $stackPtr ) === true ) { + /* + * Deprecated functions don't have to comply with the naming conventions, + * otherwise functions deprecated in favour of a function with a compliant + * name would still trigger an error. + */ + return; + } + + $methodName = $phpcsFile->getDeclarationName( $stackPtr ); + + if ( ! isset( $methodName ) ) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName( $currScope ); + if ( isset( $className ) === false ) { + $className = '[Anonymous Class]'; + } + + $methodNameLc = strtolower( $methodName ); + $classNameLc = strtolower( $className ); + + // Ignore special functions. + if ( '' === ltrim( $methodName, '_' ) ) { + return; + } + + // PHP4 constructors are allowed to break our rules. + if ( $methodNameLc === $classNameLc ) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ( '_' . $classNameLc === $methodNameLc ) { + return; + } + + $extended = $phpcsFile->findExtendedClassName( $currScope ); + $interfaces = $phpcsFile->findImplementedInterfaceNames( $currScope ); + + // If this is a child class or interface implementation, it may have to use camelCase or double underscores. + if ( ! empty( $extended ) || ! empty( $interfaces ) ) { + return; + } + + // Is this a magic method ? I.e. is it prefixed with "__" ? + if ( 0 === strpos( $methodName, '__' ) ) { + $magicPart = substr( $methodNameLc, 2 ); + if ( isset( $this->magicMethods[ $magicPart ] ) ) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $errorData = array( $className . '::' . $methodName ); + $phpcsFile->addError( $error, $stackPtr, 'MethodDoubleUnderscore', $errorData ); + } + + // Check for all lowercase. + if ( $methodNameLc !== $methodName ) { + $error = 'Method name "%s" in class %s is not in snake case format, try "%s"'; + $errorData = array( + $methodName, + $className, + Sniff::get_snake_case_name_suggestion( $methodName ), + ); + $phpcsFile->addError( $error, $stackPtr, 'MethodNameInvalid', $errorData ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php new file mode 100644 index 000000000..da62331d5 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php @@ -0,0 +1,289 @@ + + * + * + * + * + * + * Provide several extra delimiters as one string: + * + * + * + * + * + * + * @var string + */ + public $additionalWordDelimiters = ''; + + /** + * Regular expression to test for correct punctuation of a hook name. + * + * The placeholder will be replaced by potentially provided additional + * word delimiters in the `prepare_regex()` method. + * + * @var string + */ + protected $punctuation_regex = '`[^\w%s]`'; + + /** + * Groups of functions to restrict. + * + * @since 0.11.0 + * + * @return array + */ + public function getGroups() { + $this->target_functions = $this->hookInvokeFunctions; + + // No need to examine the names of deprecated hooks. + unset( + $this->target_functions['do_action_deprecated'], + $this->target_functions['apply_filters_deprecated'] + ); + + return parent::getGroups(); + } + + /** + * Process the parameters of a matched function. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + $regex = $this->prepare_regex(); + + $case_errors = 0; + $underscores = 0; + $content = array(); + $expected = array(); + + for ( $i = $parameters[1]['start']; $i <= $parameters[1]['end']; $i++ ) { + // Skip past comment tokens. + if ( isset( Tokens::$commentTokens[ $this->tokens[ $i ]['code'] ] ) !== false ) { + continue; + } + + $content[ $i ] = $this->tokens[ $i ]['content']; + $expected[ $i ] = $this->tokens[ $i ]['content']; + + // Skip past potential variable array access: $var['Key']. + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] ) { + do { + $open_bracket = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( false === $open_bracket + || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $open_bracket ]['code'] + || ! isset( $this->tokens[ $open_bracket ]['bracket_closer'] ) + ) { + continue 2; + } + + $i = $this->tokens[ $open_bracket ]['bracket_closer']; + + } while ( isset( $this->tokens[ $i ] ) && $i <= $parameters[1]['end'] ); + + continue; + } + + // Skip past non-string tokens. + if ( isset( Tokens::$stringTokens[ $this->tokens[ $i ]['code'] ] ) === false ) { + continue; + } + + $string = $this->strip_quotes( $this->tokens[ $i ]['content'] ); + + /* + * Here be dragons - a double quoted string can contain extrapolated variables + * which don't have to comply with these rules. + */ + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $i ]['code'] ) { + $transform = $this->transform_complex_string( $string, $regex ); + $case_transform = $this->transform_complex_string( $string, $regex, 'case' ); + $punct_transform = $this->transform_complex_string( $string, $regex, 'punctuation' ); + } else { + $transform = $this->transform( $string, $regex ); + $case_transform = $this->transform( $string, $regex, 'case' ); + $punct_transform = $this->transform( $string, $regex, 'punctuation' ); + } + + if ( $string === $transform ) { + continue; + } + + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $i ]['code'] ) { + $expected[ $i ] = '"' . $transform . '"'; + } else { + $expected[ $i ] = '\'' . $transform . '\''; + } + + if ( $string !== $case_transform ) { + $case_errors++; + } + if ( $string !== $punct_transform ) { + $underscores++; + } + } + + $first_non_empty = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameters[1]['start'], + ( $parameters[1]['end'] + 1 ), + true + ); + + $data = array( + trim( implode( '', $expected ) ), + trim( implode( '', $content ) ), + ); + + if ( $case_errors > 0 ) { + $error = 'Hook names should be lowercase. Expected: %s, but found: %s.'; + $this->phpcsFile->addError( $error, $first_non_empty, 'NotLowercase', $data ); + } + if ( $underscores > 0 ) { + $error = 'Words in hook names should be separated using underscores. Expected: %s, but found: %s.'; + $this->phpcsFile->addWarning( $error, $first_non_empty, 'UseUnderscores', $data ); + } + } + + /** + * Prepare the punctuation regular expression. + * + * Merges the existing regular expression with potentially provided extra word delimiters to allow. + * This is done 'late' and for each found token as otherwise inline `phpcs:set` directives + * would be ignored. + * + * @return string + */ + protected function prepare_regex() { + $extra = ''; + if ( '' !== $this->additionalWordDelimiters && \is_string( $this->additionalWordDelimiters ) ) { + $extra = preg_quote( $this->additionalWordDelimiters, '`' ); + } + + return sprintf( $this->punctuation_regex, $extra ); + } + + /** + * Transform an arbitrary string to lowercase and replace punctuation and spaces with underscores. + * + * @param string $string The target string. + * @param string $regex The punctuation regular expression to use. + * @param string $transform_type Whether to a partial or complete transform. + * Valid values are: 'full', 'case', 'punctuation'. + * @return string + */ + protected function transform( $string, $regex, $transform_type = 'full' ) { + + switch ( $transform_type ) { + case 'case': + return strtolower( $string ); + + case 'punctuation': + return preg_replace( $regex, '_', $string ); + + case 'full': + default: + return preg_replace( $regex, '_', strtolower( $string ) ); + } + } + + /** + * Transform a complex string which may contain variable extrapolation. + * + * @param string $string The target string. + * @param string $regex The punctuation regular expression to use. + * @param string $transform_type Whether to a partial or complete transform. + * Valid values are: 'full', 'case', 'punctuation'. + * @return string + */ + protected function transform_complex_string( $string, $regex, $transform_type = 'full' ) { + $output = preg_split( '`([\{\}\$\[\] ])`', $string, -1, \PREG_SPLIT_DELIM_CAPTURE ); + + $is_variable = false; + $has_braces = false; + $braces = 0; + + foreach ( $output as $i => $part ) { + if ( \in_array( $part, array( '$', '{' ), true ) ) { + $is_variable = true; + if ( '{' === $part ) { + $has_braces = true; + $braces++; + } + continue; + } + + if ( true === $is_variable ) { + if ( '[' === $part ) { + $has_braces = true; + $braces++; + } + if ( \in_array( $part, array( '}', ']' ), true ) ) { + $braces--; + } + if ( false === $has_braces && ' ' === $part ) { + $is_variable = false; + $output[ $i ] = $this->transform( $part, $regex, $transform_type ); + } + + if ( ( true === $has_braces && 0 === $braces ) && false === \in_array( $output[ ( $i + 1 ) ], array( '{', '[' ), true ) ) { + $has_braces = false; + $is_variable = false; + } + continue; + } + + $output[ $i ] = $this->transform( $part, $regex, $transform_type ); + } + + return implode( '', $output ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php new file mode 100644 index 000000000..caedae8b3 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -0,0 +1,208 @@ + true, + ); + + /** + * Array of reserved post type names which can not be used by themes and plugins. + * + * @since 2.2.0 + * + * @var array + */ + protected $reserved_names = array( + 'post' => true, + 'page' => true, + 'attachment' => true, + 'revision' => true, + 'nav_menu_item' => true, + 'custom_css' => true, + 'customize_changeset' => true, + 'oembed_cache' => true, + 'user_request' => true, + 'wp_block' => true, + 'action' => true, + 'author' => true, + 'order' => true, + 'theme' => true, + ); + + /** + * All valid tokens for in the first parameter of register_post_type(). + * + * Set in `register()`. + * + * @since 2.2.0 + * + * @var string + */ + private $valid_tokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 2.2.0 + * + * @return array + */ + public function register() { + $this->valid_tokens = Tokens::$textStringTokens + Tokens::$heredocTokens + Tokens::$emptyTokens; + return parent::register(); + } + + /** + * Process the parameter of a matched function. + * + * Errors on invalid post type names when reserved keywords are used, + * the post type is too long, or contains invalid characters. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param array $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + $string_pos = $this->phpcsFile->findNext( Tokens::$textStringTokens, $parameters[1]['start'], ( $parameters[1]['end'] + 1 ) ); + $has_invalid_tokens = $this->phpcsFile->findNext( $this->valid_tokens, $parameters[1]['start'], ( $parameters[1]['end'] + 1 ), true ); + if ( false !== $has_invalid_tokens || false === $string_pos ) { + // Check for non string based slug parameter (we cannot determine if this is valid). + $this->phpcsFile->addWarning( + 'The post type slug is not a string literal. It is not possible to automatically determine the validity of this slug. Found: %s.', + $stackPtr, + 'NotStringLiteral', + array( + $parameters[1]['raw'], + ), + 3 + ); + return; + } + + $post_type = $this->strip_quotes( $this->tokens[ $string_pos ]['content'] ); + + if ( strlen( $post_type ) === 0 ) { + // Error for using empty slug. + $this->phpcsFile->addError( + 'register_post_type() called without a post type slug. The slug must be a non-empty string.', + $parameters[1]['start'], + 'Empty' + ); + return; + } + + $data = array( + $this->tokens[ $string_pos ]['content'], + ); + + // Warn for dynamic parts in the slug parameter. + if ( 'T_DOUBLE_QUOTED_STRING' === $this->tokens[ $string_pos ]['type'] || ( 'T_HEREDOC' === $this->tokens[ $string_pos ]['type'] && strpos( $this->tokens[ $string_pos ]['content'], '$' ) !== false ) ) { + $this->phpcsFile->addWarning( + 'The post type slug may, or may not, get too long with dynamic contents and could contain invalid characters. Found: %s.', + $string_pos, + 'PartiallyDynamic', + $data + ); + $post_type = $this->strip_interpolated_variables( $post_type ); + } + + if ( preg_match( self::POST_TYPE_CHARACTER_WHITELIST, $post_type ) === 0 ) { + // Error for invalid characters. + $this->phpcsFile->addError( + 'register_post_type() called with invalid post type %s. Post type contains invalid characters. Only lowercase alphanumeric characters, dashes, and underscores are allowed.', + $string_pos, + 'InvalidCharacters', + $data + ); + } + + if ( isset( $this->reserved_names[ $post_type ] ) ) { + // Error for using reserved slug names. + $this->phpcsFile->addError( + 'register_post_type() called with reserved post type %s. Reserved post types should not be used as they interfere with the functioning of WordPress itself.', + $string_pos, + 'Reserved', + $data + ); + } elseif ( stripos( $post_type, 'wp_' ) === 0 ) { + // Error for using reserved slug prefix. + $this->phpcsFile->addError( + 'The post type passed to register_post_type() uses a prefix reserved for WordPress itself. Found: %s.', + $string_pos, + 'ReservedPrefix', + $data + ); + } + + // Error for slugs that are too long. + if ( strlen( $post_type ) > self::POST_TYPE_MAX_LENGTH ) { + $this->phpcsFile->addError( + 'A post type slug must not exceed %d characters. Found: %s (%d characters).', + $string_pos, + 'TooLong', + array( + self::POST_TYPE_MAX_LENGTH, + $this->tokens[ $string_pos ]['content'], + strlen( $post_type ), + ) + ); + } + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..34314ff18 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,299 @@ + true, + 'GETID3_ERRORARRAY' => true, + 'is_IE' => true, + 'is_IIS' => true, + 'is_macIE' => true, + 'is_NS4' => true, + 'is_winIE' => true, + 'PHP_SELF' => true, + 'post_ID' => true, + 'tag_ID' => true, + 'user_ID' => true, + ); + + /** + * List of member variables that can have mixed case. + * + * @since 0.9.0 + * @since 0.11.0 Changed from public to protected. + * + * @var array + */ + protected $whitelisted_mixed_case_member_var_names = array( + 'ID' => true, + 'comment_ID' => true, + 'comment_post_ID' => true, + 'post_ID' => true, + 'comment_author_IP' => true, + 'cat_ID' => true, + ); + + /** + * Custom list of properties which can have mixed case. + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $customPropertiesWhitelist = array(); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.10.0 + * @since 0.11.0 - Name changed from $addedCustomVariables. + * - Changed the format from simple bool to array. + * + * @var array + */ + protected $addedCustomProperties = array( + 'properties' => null, + ); + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable( File $phpcs_file, $stack_ptr ) { + + $tokens = $phpcs_file->getTokens(); + $var_name = ltrim( $tokens[ $stack_ptr ]['content'], '$' ); + + // If it's a php reserved var, then its ok. + if ( isset( $this->phpReservedVars[ $var_name ] ) ) { + return; + } + + // Merge any custom variables with the defaults. + $this->mergeWhiteList(); + + // Likewise if it is a mixed-case var used by WordPress core. + if ( isset( $this->wordpress_mixed_case_vars[ $var_name ] ) ) { + return; + } + + $obj_operator = $phpcs_file->findNext( Tokens::$emptyTokens, ( $stack_ptr + 1 ), null, true ); + if ( \T_OBJECT_OPERATOR === $tokens[ $obj_operator ]['code'] ) { + // Check to see if we are using a variable from an object. + $var = $phpcs_file->findNext( Tokens::$emptyTokens, ( $obj_operator + 1 ), null, true ); + if ( \T_STRING === $tokens[ $var ]['code'] ) { + $bracket = $phpcs_file->findNext( Tokens::$emptyTokens, ( $var + 1 ), null, true ); + if ( \T_OPEN_PARENTHESIS !== $tokens[ $bracket ]['code'] ) { + $obj_var_name = $tokens[ $var ]['content']; + + // There is no way for us to know if the var is public or + // private, so we have to ignore a leading underscore if there is + // one and just check the main part of the variable name. + $original_var_name = $obj_var_name; + if ( '_' === substr( $obj_var_name, 0, 1 ) ) { + $obj_var_name = substr( $obj_var_name, 1 ); + } + + if ( ! isset( $this->whitelisted_mixed_case_member_var_names[ $obj_var_name ] ) && self::isSnakeCase( $obj_var_name ) === false ) { + $error = 'Object property "$%s" is not in valid snake_case format, try "$%s"'; + $data = array( + $original_var_name, + Sniff::get_snake_case_name_suggestion( $original_var_name ), + ); + $phpcs_file->addError( $error, $var, 'UsedPropertyNotSnakeCase', $data ); + } + } + } + } + + $in_class = false; + $obj_operator = $phpcs_file->findPrevious( Tokens::$emptyTokens, ( $stack_ptr - 1 ), null, true ); + if ( \T_DOUBLE_COLON === $tokens[ $obj_operator ]['code'] || \T_OBJECT_OPERATOR === $tokens[ $obj_operator ]['code'] ) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable or $class->variable. + $in_class = true; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $original_var_name = $var_name; + if ( '_' === substr( $var_name, 0, 1 ) && true === $in_class ) { + $var_name = substr( $var_name, 1 ); + } + + if ( self::isSnakeCase( $var_name ) === false ) { + if ( $in_class && ! isset( $this->whitelisted_mixed_case_member_var_names[ $var_name ] ) ) { + $error = 'Object property "$%s" is not in valid snake_case format, try "$%s"'; + $error_name = 'UsedPropertyNotSnakeCase'; + } elseif ( ! $in_class ) { + $error = 'Variable "$%s" is not in valid snake_case format, try "$%s"'; + $error_name = 'VariableNotSnakeCase'; + } + + if ( isset( $error, $error_name ) ) { + $data = array( + $original_var_name, + Sniff::get_snake_case_name_suggestion( $original_var_name ), + ); + $phpcs_file->addError( $error, $stack_ptr, $error_name, $data ); + } + } + } + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar( File $phpcs_file, $stack_ptr ) { + + $tokens = $phpcs_file->getTokens(); + + $var_name = ltrim( $tokens[ $stack_ptr ]['content'], '$' ); + $member_props = $phpcs_file->getMemberProperties( $stack_ptr ); + if ( empty( $member_props ) ) { + // Couldn't get any info about this variable, which + // generally means it is invalid or possibly has a parse + // error. Any errors will be reported by the core, so + // we can ignore it. + return; + } + + // Merge any custom variables with the defaults. + $this->mergeWhiteList(); + + if ( ! isset( $this->whitelisted_mixed_case_member_var_names[ $var_name ] ) && false === self::isSnakeCase( $var_name ) ) { + $error = 'Member variable "$%s" is not in valid snake_case format, try "$%s"'; + $data = array( + $var_name, + Sniff::get_snake_case_name_suggestion( $var_name ), + ); + $phpcs_file->addError( $error, $stack_ptr, 'PropertyNotSnakeCase', $data ); + } + } + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString( File $phpcs_file, $stack_ptr ) { + + $tokens = $phpcs_file->getTokens(); + + if ( preg_match_all( '|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[ $stack_ptr ]['content'], $matches ) > 0 ) { + + // Merge any custom variables with the defaults. + $this->mergeWhiteList(); + + foreach ( $matches[1] as $var_name ) { + // If it's a php reserved var, then its ok. + if ( isset( $this->phpReservedVars[ $var_name ] ) ) { + continue; + } + + // Likewise if it is a mixed-case var used by WordPress core. + if ( isset( $this->wordpress_mixed_case_vars[ $var_name ] ) ) { + return; + } + + if ( false === self::isSnakeCase( $var_name ) ) { + $error = 'Variable "$%s" is not in valid snake_case format, try "$%s"'; + $data = array( + $var_name, + Sniff::get_snake_case_name_suggestion( $var_name ), + ); + $phpcs_file->addError( $error, $stack_ptr, 'InterpolatedVariableNotSnakeCase', $data ); + } + } + } + } + + /** + * Return whether the variable is in snake_case. + * + * @param string $var_name Variable name. + * @return bool + */ + public static function isSnakeCase( $var_name ) { + return (bool) preg_match( '/^[a-z0-9_]+$/', $var_name ); + } + + /** + * Merge a custom whitelist provided via a custom ruleset with the predefined whitelist, + * if we haven't already. + * + * @since 0.10.0 + * @since 2.0.0 Removed unused $phpcs_file parameter. + * + * @return void + */ + protected function mergeWhiteList() { + if ( $this->customPropertiesWhitelist !== $this->addedCustomProperties['properties'] ) { + // Fix property potentially passed as comma-delimited string. + $customProperties = Sniff::merge_custom_array( $this->customPropertiesWhitelist, array(), false ); + + $this->whitelisted_mixed_case_member_var_names = Sniff::merge_custom_array( + $customProperties, + $this->whitelisted_mixed_case_member_var_names + ); + + $this->addedCustomProperties['properties'] = $this->customPropertiesWhitelist; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php new file mode 100644 index 000000000..59e914dcf --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DevelopmentFunctionsSniff.php @@ -0,0 +1,66 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'error_log' => array( + 'type' => 'warning', + 'message' => '%s() found. Debug code should not normally be used in production.', + 'functions' => array( + 'error_log', + 'var_dump', + 'var_export', + 'print_r', + 'trigger_error', + 'set_error_handler', + 'debug_backtrace', + 'debug_print_backtrace', + 'wp_debug_backtrace_summary', + ), + ), + + 'prevent_path_disclosure' => array( + 'type' => 'warning', + 'message' => '%s() can lead to full path disclosure.', + 'functions' => array( + 'error_reporting', + 'phpinfo', + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php new file mode 100644 index 000000000..6c734b8ce --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DisallowShortTernarySniff.php @@ -0,0 +1,65 @@ +phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false === $nextNonEmpty ) { + // Live coding or parse error. + return; + } + + if ( \T_INLINE_ELSE !== $this->tokens[ $nextNonEmpty ]['code'] ) { + return; + } + + $this->phpcsFile->addError( + 'Using short ternaries is not allowed', + $stackPtr, + 'Found' + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php new file mode 100644 index 000000000..39f87c098 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DiscouragedPHPFunctionsSniff.php @@ -0,0 +1,103 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'serialize' => array( + 'type' => 'warning', + 'message' => '%s() found. Serialized data has known vulnerability problems with Object Injection. JSON is generally a better approach for serializing data. See https://www.owasp.org/index.php/PHP_Object_Injection', + 'functions' => array( + 'serialize', + 'unserialize', + ), + ), + + 'urlencode' => array( + 'type' => 'warning', + 'message' => '%s() should only be used when dealing with legacy applications rawurlencode() should now be used instead. See http://php.net/manual/en/function.rawurlencode.php and http://www.faqs.org/rfcs/rfc3986.html', + 'functions' => array( + 'urlencode', + ), + ), + + 'runtime_configuration' => array( + 'type' => 'warning', + 'message' => '%s() found. Changing configuration values at runtime is strongly discouraged.', + 'functions' => array( + 'error_reporting', + 'ini_restore', + 'apache_setenv', + 'putenv', + 'set_include_path', + 'restore_include_path', + // This alias was DEPRECATED in PHP 5.3.0, and REMOVED as of PHP 7.0.0. + 'magic_quotes_runtime', + // Warning This function was DEPRECATED in PHP 5.3.0, and REMOVED as of PHP 7.0.0. + 'set_magic_quotes_runtime', + // Warning This function was removed from most SAPIs in PHP 5.3.0, and was removed from PHP-FPM in PHP 7.0.0. + 'dl', + ), + ), + + 'system_calls' => array( + 'type' => 'warning', + 'message' => '%s() found. PHP system calls are often disabled by server admins.', + 'functions' => array( + 'exec', + 'passthru', + 'proc_open', + 'shell_exec', + 'system', + 'popen', + ), + ), + + 'obfuscation' => array( + 'type' => 'warning', + 'message' => '%s() can be used to obfuscate code which is strongly discouraged. Please verify that the function is used for benign reasons.', + 'functions' => array( + 'base64_decode', + 'base64_encode', + 'convert_uudecode', + 'convert_uuencode', + 'str_rot13', + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php new file mode 100644 index 000000000..af2233bbe --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/DontExtractSniff.php @@ -0,0 +1,55 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + + 'extract' => array( + 'type' => 'error', + 'message' => '%s() usage is highly discouraged, due to the complexity and unintended issues it might cause.', + 'functions' => array( + 'extract', + ), + ), + + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php new file mode 100644 index 000000000..178386d11 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/IniSetSniff.php @@ -0,0 +1,177 @@ + true, + 'ini_alter' => true, + ); + + /** + * Array of PHP configuration options that are allowed to be manipulated. + * + * @since 2.1.0 + * + * @var array Multidimensional array with parameter details. + * $whitelisted_options = array( + * (string) option name. = array( + * (string[]) 'valid_values' = array() + * ) + * ); + */ + protected $whitelisted_options = array( + 'auto_detect_line_endings' => array(), + 'highlight.bg' => array(), + 'highlight.comment' => array(), + 'highlight.default' => array(), + 'highlight.html' => array(), + 'highlight.keyword' => array(), + 'highlight.string' => array(), + 'short_open_tag' => array( + 'valid_values' => array( 'true', '1', 'on' ), + ), + ); + + /** + * Array of PHP configuration options that are not allowed to be manipulated. + * + * @since 2.1.0 + * + * @var array Multidimensional array with parameter details. + * $blacklisted_options = array( + * (string) option name. = array( + * (string[]) 'invalid_values' = array() + * (string) 'message' + * ) + * ); + */ + protected $blacklisted_options = array( + 'bcmath.scale' => array( + 'message' => 'Use `bcscale()` instead.', + ), + 'display_errors' => array( + 'message' => 'Use `WP_DEBUG_DISPLAY` instead.', + ), + 'error_reporting' => array( + 'message' => 'Use `WP_DEBUG` instead.', + ), + 'filter.default' => array( + 'message' => 'Changing the option value can break other plugins. Use the filter flag constants when calling the Filter functions instead.', + ), + 'filter.default_flags' => array( + 'message' => 'Changing the option value can break other plugins. Use the filter flag constants when calling the Filter functions instead.', + ), + 'iconv.input_encoding' => array( + 'message' => 'PHP < 5.6 only - use `iconv_set_encoding()` instead.', + ), + 'iconv.internal_encoding' => array( + 'message' => 'PHP < 5.6 only - use `iconv_set_encoding()` instead.', + ), + 'iconv.output_encoding' => array( + 'message' => 'PHP < 5.6 only - use `iconv_set_encoding()` instead.', + ), + 'ignore_user_abort' => array( + 'message' => 'Use `ignore_user_abort()` instead.', + ), + 'log_errors' => array( + 'message' => 'Use `WP_DEBUG_LOG` instead.', + ), + 'max_execution_time' => array( + 'message' => 'Use `set_time_limit()` instead.', + ), + 'memory_limit' => array( + 'message' => 'Use `wp_raise_memory_limit()` or hook into the filters in that function.', + ), + 'short_open_tag' => array( + 'invalid_values' => array( 'false', '0', 'off' ), + 'message' => 'Turning off short_open_tag is prohibited as it can break other plugins.', + ), + ); + + /** + * Process the parameter of a matched function. + * + * Errors if an option is found in the blacklist. Warns as + * 'risky' when the option is not found in the whitelist. + * + * @since 2.1.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $option_name = $this->strip_quotes( $parameters[1]['raw'] ); + $option_value = $this->strip_quotes( $parameters[2]['raw'] ); + if ( isset( $this->whitelisted_options[ $option_name ] ) ) { + $whitelisted_option = $this->whitelisted_options[ $option_name ]; + if ( ! isset( $whitelisted_option['valid_values'] ) || in_array( strtolower( $option_value ), $whitelisted_option['valid_values'], true ) ) { + return; + } + } + + if ( isset( $this->blacklisted_options[ $option_name ] ) ) { + $blacklisted_option = $this->blacklisted_options[ $option_name ]; + if ( ! isset( $blacklisted_option['invalid_values'] ) || in_array( strtolower( $option_value ), $blacklisted_option['invalid_values'], true ) ) { + $this->phpcsFile->addError( + '%s(%s, %s) found. %s', + $stackPtr, + $this->string_to_errorcode( $option_name . '_Blacklisted' ), + array( + $matched_content, + $parameters[1]['raw'], + $parameters[2]['raw'], + $blacklisted_option['message'], + ) + ); + return; + } + } + + $this->phpcsFile->addWarning( + '%s(%s, %s) found. Changing configuration values at runtime is strongly discouraged.', + $stackPtr, + 'Risky', + array( + $matched_content, + $parameters[1]['raw'], + $parameters[2]['raw'], + ) + ); + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php new file mode 100644 index 000000000..ee3b3b3a5 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/NoSilencedErrorsSniff.php @@ -0,0 +1,239 @@ + => + */ + protected $function_whitelist = array( + // Directory extension. + 'chdir' => true, + 'opendir' => true, + 'scandir' => true, + + // File extension. + 'file_exists' => true, + 'file_get_contents' => true, + 'file' => true, + 'fileatime' => true, + 'filectime' => true, + 'filegroup' => true, + 'fileinode' => true, + 'filemtime' => true, + 'fileowner' => true, + 'fileperms' => true, + 'filesize' => true, + 'filetype' => true, + 'fopen' => true, + 'is_dir' => true, + 'is_executable' => true, + 'is_file' => true, + 'is_link' => true, + 'is_readable' => true, + 'is_writable' => true, + 'is_writeable' => true, + 'lstat' => true, + 'mkdir' => true, + 'move_uploaded_file' => true, + 'readfile' => true, + 'readlink' => true, + 'rename' => true, + 'rmdir' => true, + 'stat' => true, + 'unlink' => true, + + // FTP extension. + 'ftp_chdir' => true, + 'ftp_login' => true, + 'ftp_rename' => true, + + // Stream extension. + 'stream_select' => true, + 'stream_set_chunk_size' => true, + + // Zlib extension. + 'deflate_add' => true, + 'deflate_init' => true, + 'inflate_add' => true, + 'inflate_init' => true, + 'readgzfile' => true, + + // Miscellaneous other functions. + 'imagecreatefromstring' => true, + 'parse_url' => true, // Pre-PHP 5.3.3 an E_WARNING was thrown when URL parsing failed. + 'unserialize' => true, + ); + + /** + * Tokens which are regarded as empty for the purpose of determining + * the name of the called function. + * + * This property is set from within the register() method. + * + * @since 1.1.0 + * + * @var array + */ + private $empty_tokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 1.1.0 + * + * @return array + */ + public function register() { + $this->empty_tokens = Tokens::$emptyTokens; + $this->empty_tokens[ \T_NS_SEPARATOR ] = \T_NS_SEPARATOR; + $this->empty_tokens[ \T_BITWISE_AND ] = \T_BITWISE_AND; + + return array( + \T_ASPERAND, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.1.0 + * + * @param int $stackPtr The position of the current token in the stack. + */ + public function process_token( $stackPtr ) { + // Handle the user-defined custom function whitelist. + $this->custom_whitelist = $this->merge_custom_array( $this->custom_whitelist, array(), false ); + $this->custom_whitelist = array_map( 'strtolower', $this->custom_whitelist ); + + /* + * Check if the error silencing is done for one of the whitelisted functions. + * + * @internal The function call name determination is done even when there is no whitelist active + * to allow the metrics to be more informative. + */ + $next_non_empty = $this->phpcsFile->findNext( $this->empty_tokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false !== $next_non_empty && \T_STRING === $this->tokens[ $next_non_empty ]['code'] ) { + $has_parenthesis = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true, null, true ); + if ( false !== $has_parenthesis && \T_OPEN_PARENTHESIS === $this->tokens[ $has_parenthesis ]['code'] ) { + $function_name = strtolower( $this->tokens[ $next_non_empty ]['content'] ); + if ( ( true === $this->use_default_whitelist + && isset( $this->function_whitelist[ $function_name ] ) === true ) + || ( ! empty( $this->custom_whitelist ) + && in_array( $function_name, $this->custom_whitelist, true ) === true ) + ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Error silencing', 'whitelisted function call: ' . $function_name ); + return; + } + } + } + + $this->context_length = (int) $this->context_length; + $context_length = $this->context_length; + if ( $this->context_length <= 0 ) { + $context_length = 2; + } + + // Prepare the "Found" string to display. + $end_of_statement = $this->phpcsFile->findEndOfStatement( $stackPtr, \T_COMMA ); + if ( ( $end_of_statement - $stackPtr ) < $context_length ) { + $context_length = ( $end_of_statement - $stackPtr ); + } + $found = $this->phpcsFile->getTokensAsString( $stackPtr, $context_length ); + $found = str_replace( array( "\t", "\n", "\r" ), ' ', $found ) . '...'; + + $error_msg = 'Silencing errors is strongly discouraged. Use proper error checking instead.'; + $data = array(); + if ( $this->context_length > 0 ) { + $error_msg .= ' Found: %s'; + $data[] = $found; + } + + $this->phpcsFile->addWarning( + $error_msg, + $stackPtr, + 'Discouraged', + $data + ); + + if ( isset( $function_name ) ) { + $this->phpcsFile->recordMetric( $stackPtr, 'Error silencing', '@' . $function_name ); + } else { + $this->phpcsFile->recordMetric( $stackPtr, 'Error silencing', $found ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php new file mode 100644 index 000000000..9fb1cdcbe --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php @@ -0,0 +1,76 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'ereg' => array( + 'type' => 'error', + 'message' => '%s() has been deprecated since PHP 5.3 and removed in PHP 7.0, please use preg_match() instead.', + 'functions' => array( + 'ereg', + 'eregi', + 'sql_regcase', + ), + ), + + 'ereg_replace' => array( + 'type' => 'error', + 'message' => '%s() has been deprecated since PHP 5.3 and removed in PHP 7.0, please use preg_replace() instead.', + 'functions' => array( + 'ereg_replace', + 'eregi_replace', + ), + ), + + 'split' => array( + 'type' => 'error', + 'message' => '%s() has been deprecated since PHP 5.3 and removed in PHP 7.0, please use explode(), str_split() or preg_split() instead.', + 'functions' => array( + 'split', + 'spliti', + ), + ), + + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php new file mode 100644 index 000000000..a67e11732 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/PregQuoteDelimiterSniff.php @@ -0,0 +1,69 @@ + => + */ + protected $target_functions = array( + 'preg_quote' => true, + ); + + /** + * Process the parameters of a matched function. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + if ( \count( $parameters ) > 1 ) { + return; + } + + $this->phpcsFile->addWarning( + 'Passing the $delimiter as the second parameter to preg_quote() is strongly recommended.', + $stackPtr, + 'Missing' + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php new file mode 100644 index 000000000..280c94d91 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php @@ -0,0 +1,48 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'create_function' => array( + 'type' => 'error', + 'message' => '%s() is deprecated as of PHP 7.2, please use full fledged functions or anonymous functions instead.', + 'functions' => array( + 'create_function', + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php new file mode 100644 index 000000000..85fe05549 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictComparisonsSniff.php @@ -0,0 +1,56 @@ +has_whitelist_comment( 'loose comparison', $stackPtr ) ) { + $error = 'Found: ' . $this->tokens[ $stackPtr ]['content'] . '. Use strict comparisons (=== or !==).'; + $this->phpcsFile->addWarning( $error, $stackPtr, 'LooseComparison' ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php new file mode 100644 index 000000000..4973e9bb8 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/StrictInArraySniff.php @@ -0,0 +1,105 @@ + => + */ + protected $target_functions = array( + 'in_array' => true, + 'array_search' => true, + 'array_keys' => false, + ); + + /** + * Process the parameters of a matched function. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + // Check if the strict check is actually needed. + if ( false === $this->target_functions[ $matched_content ] ) { + if ( \count( $parameters ) === 1 ) { + return; + } + } + + // We're only interested in the third parameter. + if ( false === isset( $parameters[3] ) || 'true' !== strtolower( $parameters[3]['raw'] ) ) { + $errorcode = 'MissingTrueStrict'; + + /* + * Use a different error code when `false` is found to allow for excluding + * the warning as this will be a conscious choice made by the dev. + */ + if ( isset( $parameters[3] ) && 'false' === strtolower( $parameters[3]['raw'] ) ) { + $errorcode = 'FoundNonStrictFalse'; + } + + $this->phpcsFile->addWarning( + 'Not using strict comparison for %s; supply true for third argument.', + ( isset( $parameters[3]['start'] ) ? $parameters[3]['start'] : $parameters[1]['start'] ), + $errorcode, + array( $matched_content ) + ); + return; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php new file mode 100644 index 000000000..7aded55fe --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/TypeCastsSniff.php @@ -0,0 +1,99 @@ +tokens[ $stackPtr ]['code']; + $typecast = str_replace( ' ', '', $this->tokens[ $stackPtr ]['content'] ); + $typecast_lc = strtolower( $typecast ); + + switch ( $token_code ) { + case \T_DOUBLE_CAST: + if ( '(float)' !== $typecast_lc ) { + $fix = $this->phpcsFile->addFixableError( + 'Normalized type keywords must be used; expected "(float)" but found "%s"', + $stackPtr, + 'DoubleRealFound', + array( $typecast ) + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( $stackPtr, '(float)' ); + } + } + break; + + case \T_UNSET_CAST: + $this->phpcsFile->addWarning( + 'Using the "(unset)" cast is strongly discouraged. Use the "unset()" language construct or assign "null" as the value to the variable instead.', + $stackPtr, + 'UnsetFound' + ); + break; + + case \T_STRING_CAST: + case \T_BINARY_CAST: + if ( \T_STRING_CAST === $token_code && '(binary)' !== $typecast_lc ) { + break; + } + + $this->phpcsFile->addWarning( + 'Using binary casting is strongly discouraged. Found: "%s"', + $stackPtr, + 'BinaryFound', + array( $typecast ) + ); + break; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php new file mode 100644 index 000000000..9f3f3d10d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/PHP/YodaConditionsSniff.php @@ -0,0 +1,125 @@ +condition_start_tokens = $starters; + + return array( + \T_IS_EQUAL, + \T_IS_NOT_EQUAL, + \T_IS_IDENTICAL, + \T_IS_NOT_IDENTICAL, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $start = $this->phpcsFile->findPrevious( $this->condition_start_tokens, $stackPtr, null, false, null, true ); + + $needs_yoda = false; + + // Note: going backwards! + for ( $i = $stackPtr; $i > $start; $i-- ) { + + // Ignore whitespace. + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ( \T_VARIABLE === $this->tokens[ $i ]['code'] + || \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $i ]['code'] + ) { + $needs_yoda = true; + break; + } + + // If this is a function call or something, we are OK. + if ( \T_CLOSE_PARENTHESIS === $this->tokens[ $i ]['code'] ) { + return; + } + } + + if ( ! $needs_yoda ) { + return; + } + + // Check if this is a var to var comparison, e.g.: if ( $var1 == $var2 ). + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + if ( isset( Tokens::$castTokens[ $this->tokens[ $next_non_empty ]['code'] ] ) ) { + $next_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true ); + } + + if ( \in_array( $this->tokens[ $next_non_empty ]['code'], array( \T_SELF, \T_PARENT, \T_STATIC ), true ) ) { + $next_non_empty = $this->phpcsFile->findNext( + ( Tokens::$emptyTokens + array( \T_DOUBLE_COLON => \T_DOUBLE_COLON ) ), + ( $next_non_empty + 1 ), + null, + true + ); + } + + if ( \T_VARIABLE === $this->tokens[ $next_non_empty ]['code'] ) { + return; + } + + $this->phpcsFile->addError( 'Use Yoda Condition checks, you must.', $stackPtr, 'NotYoda' ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php new file mode 100644 index 000000000..48a4766ba --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/EscapeOutputSniff.php @@ -0,0 +1,505 @@ + 'esc_html_e() or esc_attr_e()', + '_ex' => 'echo esc_html_x() or echo esc_attr_x()', + ); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.4.0 + * @since 0.11.0 - Changed from public static to protected non-static. + * - Changed the format from simple bool to array. + * + * @var array + */ + protected $addedCustomFunctions = array( + 'escape' => array(), + 'autoescape' => array(), + 'sanitize' => array(), + 'print' => array(), + ); + + /** + * List of names of the tokens representing PHP magic constants. + * + * @since 0.10.0 + * + * @var array + */ + private $magic_constant_tokens = array( + 'T_CLASS_C' => true, // __CLASS__ + 'T_DIR' => true, // __DIR__ + 'T_FILE' => true, // __FILE__ + 'T_FUNC_C' => true, // __FUNCTION__ + 'T_LINE' => true, // __LINE__ + 'T_METHOD_C' => true, // __METHOD__ + 'T_NS_C' => true, // __NAMESPACE__ + 'T_TRAIT_C' => true, // __TRAIT__ + ); + + /** + * List of names of the native PHP constants which can be considered safe. + * + * @since 1.0.0 + * + * @var array + */ + private $safe_php_constants = array( + 'PHP_EOL' => true, // String. + 'PHP_VERSION' => true, // Integer. + 'PHP_MAJOR_VERSION' => true, // Integer. + 'PHP_MINOR_VERSION' => true, // Integer. + 'PHP_RELEASE_VERSION' => true, // Integer. + 'PHP_VERSION_ID' => true, // Integer. + 'PHP_EXTRA_VERSION' => true, // String. + 'PHP_DEBUG' => true, // Integer. + ); + + /** + * List of tokens which can be considered as safe when directly part of the output. + * + * @since 0.12.0 + * + * @var array + */ + private $safe_components = array( + 'T_CONSTANT_ENCAPSED_STRING' => true, + 'T_LNUMBER' => true, + 'T_MINUS' => true, + 'T_PLUS' => true, + 'T_MULTIPLY' => true, + 'T_DIVIDE' => true, + 'T_MODULUS' => true, + 'T_TRUE' => true, + 'T_FALSE' => true, + 'T_NULL' => true, + 'T_DNUMBER' => true, + 'T_START_NOWDOC' => true, + 'T_NOWDOC' => true, + 'T_END_NOWDOC' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + + return array( + \T_ECHO, + \T_PRINT, + \T_EXIT, + \T_STRING, + \T_OPEN_TAG_WITH_ECHO, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + $this->mergeFunctionLists(); + + $function = $this->tokens[ $stackPtr ]['content']; + + // Find the opening parenthesis (if present; T_ECHO might not have it). + $open_paren = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + // If function, not T_ECHO nor T_PRINT. + if ( \T_STRING === $this->tokens[ $stackPtr ]['code'] ) { + // Skip if it is a function but is not one of the printing functions. + if ( ! isset( $this->printingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) ) { + return; + } + + if ( isset( $this->tokens[ $open_paren ]['parenthesis_closer'] ) ) { + $end_of_statement = $this->tokens[ $open_paren ]['parenthesis_closer']; + } + + // These functions only need to have the first argument escaped. + if ( \in_array( $function, array( 'trigger_error', 'user_error' ), true ) ) { + $first_param = $this->get_function_call_parameter( $stackPtr, 1 ); + $end_of_statement = ( $first_param['end'] + 1 ); + unset( $first_param ); + } + + /* + * If the first param to `_deprecated_file()` follows the typical `basename( __FILE__ )` + * pattern, it doesn't need to be escaped. + */ + if ( '_deprecated_file' === $function ) { + $first_param = $this->get_function_call_parameter( $stackPtr, 1 ); + + // Quick check. This disregards comments. + if ( preg_match( '`^basename\s*\(\s*__FILE__\s*\)$`', $first_param['raw'] ) === 1 ) { + $stackPtr = ( $first_param['end'] + 2 ); + } + unset( $first_param ); + } + } + + // Checking for the ignore comment, ex: //xss ok. + if ( $this->has_whitelist_comment( 'xss', $stackPtr ) ) { + return; + } + + if ( isset( $this->unsafePrintingFunctions[ $function ] ) ) { + $error = $this->phpcsFile->addError( + "All output should be run through an escaping function (like %s), found '%s'.", + $stackPtr, + 'UnsafePrintingFunction', + array( $this->unsafePrintingFunctions[ $function ], $function ) + ); + + // If the error was reported, don't bother checking the function's arguments. + if ( $error ) { + return isset( $end_of_statement ) ? $end_of_statement : null; + } + } + + $ternary = false; + + // This is already determined if this is a function and not T_ECHO. + if ( ! isset( $end_of_statement ) ) { + + $end_of_statement = $this->phpcsFile->findNext( array( \T_SEMICOLON, \T_CLOSE_TAG ), $stackPtr ); + $last_token = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $end_of_statement - 1 ), null, true ); + + // Check for the ternary operator. We only need to do this here if this + // echo is lacking parenthesis. Otherwise it will be handled below. + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $open_paren ]['code'] || \T_CLOSE_PARENTHESIS !== $this->tokens[ $last_token ]['code'] ) { + + $ternary = $this->phpcsFile->findNext( \T_INLINE_THEN, $stackPtr, $end_of_statement ); + + // If there is a ternary skip over the part before the ?. However, if + // the ternary is within parentheses, it will be handled in the loop. + if ( false !== $ternary && empty( $this->tokens[ $ternary ]['nested_parenthesis'] ) ) { + $stackPtr = $ternary; + } + } + } + + // Ignore the function itself. + $stackPtr++; + + $in_cast = false; + + // Looping through echo'd components. + $watch = true; + for ( $i = $stackPtr; $i < $end_of_statement; $i++ ) { + + // Ignore whitespaces and comments. + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + // Ignore namespace separators. + if ( \T_NS_SEPARATOR === $this->tokens[ $i ]['code'] ) { + continue; + } + + if ( \T_OPEN_PARENTHESIS === $this->tokens[ $i ]['code'] ) { + + if ( ! isset( $this->tokens[ $i ]['parenthesis_closer'] ) ) { + // Live coding or parse error. + break; + } + + if ( $in_cast ) { + + // Skip to the end of a function call if it has been casted to a safe value. + $i = $this->tokens[ $i ]['parenthesis_closer']; + $in_cast = false; + + } else { + + // Skip over the condition part of a ternary (i.e., to after the ?). + $ternary = $this->phpcsFile->findNext( \T_INLINE_THEN, $i, $this->tokens[ $i ]['parenthesis_closer'] ); + + if ( false !== $ternary ) { + + $next_paren = $this->phpcsFile->findNext( \T_OPEN_PARENTHESIS, ( $i + 1 ), $this->tokens[ $i ]['parenthesis_closer'] ); + + // We only do it if the ternary isn't within a subset of parentheses. + if ( false === $next_paren || ( isset( $this->tokens[ $next_paren ]['parenthesis_closer'] ) && $ternary > $this->tokens[ $next_paren ]['parenthesis_closer'] ) ) { + $i = $ternary; + } + } + } + + continue; + } + + // Handle arrays for those functions that accept them. + if ( \T_ARRAY === $this->tokens[ $i ]['code'] ) { + $i++; // Skip the opening parenthesis. + continue; + } + + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $i ]['code'] + || \T_CLOSE_SHORT_ARRAY === $this->tokens[ $i ]['code'] + ) { + continue; + } + + if ( \in_array( $this->tokens[ $i ]['code'], array( \T_DOUBLE_ARROW, \T_CLOSE_PARENTHESIS ), true ) ) { + continue; + } + + // Handle magic constants for debug functions. + if ( isset( $this->magic_constant_tokens[ $this->tokens[ $i ]['type'] ] ) ) { + continue; + } + + // Handle safe PHP native constants. + if ( \T_STRING === $this->tokens[ $i ]['code'] + && isset( $this->safe_php_constants[ $this->tokens[ $i ]['content'] ] ) + && $this->is_use_of_global_constant( $i ) + ) { + continue; + } + + // Wake up on concatenation characters, another part to check. + if ( \T_STRING_CONCAT === $this->tokens[ $i ]['code'] ) { + $watch = true; + continue; + } + + // Wake up after a ternary else (:). + if ( false !== $ternary && \T_INLINE_ELSE === $this->tokens[ $i ]['code'] ) { + $watch = true; + continue; + } + + // Wake up for commas. + if ( \T_COMMA === $this->tokens[ $i ]['code'] ) { + $in_cast = false; + $watch = true; + continue; + } + + if ( false === $watch ) { + continue; + } + + // Allow T_CONSTANT_ENCAPSED_STRING eg: echo 'Some String'; + // Also T_LNUMBER, e.g.: echo 45; exit -1; and booleans. + if ( isset( $this->safe_components[ $this->tokens[ $i ]['type'] ] ) ) { + continue; + } + + $watch = false; + + // Allow int/double/bool casted variables. + if ( isset( $this->safe_casts[ $this->tokens[ $i ]['code'] ] ) ) { + $in_cast = true; + continue; + } + + // Now check that next token is a function call. + if ( \T_STRING === $this->tokens[ $i ]['code'] ) { + + $ptr = $i; + $functionName = $this->tokens[ $i ]['content']; + $function_opener = $this->phpcsFile->findNext( \T_OPEN_PARENTHESIS, ( $i + 1 ), null, false, null, true ); + $is_formatting_function = isset( $this->formattingFunctions[ $functionName ] ); + + if ( false !== $function_opener ) { + + if ( isset( $this->arrayWalkingFunctions[ $functionName ] ) ) { + + // Get the callback parameter. + $callback = $this->get_function_call_parameter( + $ptr, + $this->arrayWalkingFunctions[ $functionName ] + ); + + if ( ! empty( $callback ) ) { + /* + * If this is a function callback (not a method callback array) and we're able + * to resolve the function name, do so. + */ + $mapped_function = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $callback['start'], + ( $callback['end'] + 1 ), + true + ); + + if ( false !== $mapped_function + && \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $mapped_function ]['code'] + ) { + $functionName = $this->strip_quotes( $this->tokens[ $mapped_function ]['content'] ); + $ptr = $mapped_function; + } + } + } + + // Skip pointer to after the function. + // If this is a formatting function we just skip over the opening + // parenthesis. Otherwise we skip all the way to the closing. + if ( $is_formatting_function ) { + $i = ( $function_opener + 1 ); + $watch = true; + } else { + if ( isset( $this->tokens[ $function_opener ]['parenthesis_closer'] ) ) { + $i = $this->tokens[ $function_opener ]['parenthesis_closer']; + } else { + // Live coding or parse error. + break; + } + } + } + + // If this is a safe function, we don't flag it. + if ( + $is_formatting_function + || isset( $this->autoEscapedFunctions[ $functionName ] ) + || isset( $this->escapingFunctions[ $functionName ] ) + ) { + continue; + } + + $content = $functionName; + + } else { + $content = $this->tokens[ $i ]['content']; + $ptr = $i; + } + + // Make the error message a little more informative for array access variables. + if ( \T_VARIABLE === $this->tokens[ $ptr ]['code'] ) { + $array_keys = $this->get_array_access_keys( $ptr ); + + if ( ! empty( $array_keys ) ) { + $content .= '[' . implode( '][', $array_keys ) . ']'; + } + } + + $this->phpcsFile->addError( + "All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '%s'.", + $ptr, + 'OutputNotEscaped', + array( $content ) + ); + } + + return $end_of_statement; + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( $this->customEscapingFunctions !== $this->addedCustomFunctions['escape'] ) { + $customEscapeFunctions = $this->merge_custom_array( $this->customEscapingFunctions, array(), false ); + + $this->escapingFunctions = $this->merge_custom_array( + $customEscapeFunctions, + $this->escapingFunctions + ); + + $this->addedCustomFunctions['escape'] = $this->customEscapingFunctions; + } + + if ( $this->customAutoEscapedFunctions !== $this->addedCustomFunctions['autoescape'] ) { + $this->autoEscapedFunctions = $this->merge_custom_array( + $this->customAutoEscapedFunctions, + $this->autoEscapedFunctions + ); + + $this->addedCustomFunctions['autoescape'] = $this->customAutoEscapedFunctions; + } + + if ( $this->customPrintingFunctions !== $this->addedCustomFunctions['print'] ) { + + $this->printingFunctions = $this->merge_custom_array( + $this->customPrintingFunctions, + $this->printingFunctions + ); + + $this->addedCustomFunctions['print'] = $this->customPrintingFunctions; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php new file mode 100644 index 000000000..15f4a6040 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/NonceVerificationSniff.php @@ -0,0 +1,178 @@ + true, + '$_FILE' => true, + '$_GET' => false, + '$_REQUEST' => false, + ); + + /** + * Custom list of functions which verify nonces. + * + * @since 0.5.0 + * + * @var string|string[] + */ + public $customNonceVerificationFunctions = array(); + + /** + * Custom list of functions that sanitize the values passed to them. + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $customSanitizingFunctions = array(); + + /** + * Custom sanitizing functions that implicitly unslash the values passed to them. + * + * @since 0.11.0 + * + * @var string|string[] + */ + public $customUnslashingSanitizingFunctions = array(); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.5.0 + * @since 0.11.0 - Changed from public static to protected non-static. + * - Changed the format from simple bool to array. + * + * @var array + */ + protected $addedCustomFunctions = array( + 'nonce' => array(), + 'sanitize' => array(), + 'unslashsanitize' => array(), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + + return array( + \T_VARIABLE, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $instance = $this->tokens[ $stackPtr ]; + + if ( ! isset( $this->superglobals[ $instance['content'] ] ) ) { + return; + } + + if ( $this->has_whitelist_comment( 'CSRF', $stackPtr ) ) { + return; + } + + if ( $this->is_assignment( $stackPtr ) ) { + return; + } + + $this->mergeFunctionLists(); + + if ( $this->has_nonce_check( $stackPtr ) ) { + return; + } + + $error_code = 'Missing'; + if ( false === $this->superglobals[ $instance['content'] ] ) { + $error_code = 'Recommended'; + } + + // If we're still here, no nonce-verification function was found. + $this->addMessage( + 'Processing form data without nonce verification.', + $stackPtr, + $this->superglobals[ $instance['content'] ], + $error_code + ); + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( $this->customNonceVerificationFunctions !== $this->addedCustomFunctions['nonce'] ) { + $this->nonceVerificationFunctions = $this->merge_custom_array( + $this->customNonceVerificationFunctions, + $this->nonceVerificationFunctions + ); + + $this->addedCustomFunctions['nonce'] = $this->customNonceVerificationFunctions; + } + + if ( $this->customSanitizingFunctions !== $this->addedCustomFunctions['sanitize'] ) { + $this->sanitizingFunctions = $this->merge_custom_array( + $this->customSanitizingFunctions, + $this->sanitizingFunctions + ); + + $this->addedCustomFunctions['sanitize'] = $this->customSanitizingFunctions; + } + + if ( $this->customUnslashingSanitizingFunctions !== $this->addedCustomFunctions['unslashsanitize'] ) { + $this->unslashingSanitizingFunctions = $this->merge_custom_array( + $this->customUnslashingSanitizingFunctions, + $this->unslashingSanitizingFunctions + ); + + $this->addedCustomFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php new file mode 100644 index 000000000..08d8d58e0 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/PluginMenuSlugSniff.php @@ -0,0 +1,89 @@ + => + */ + protected $target_functions = array( + 'add_menu_page' => array( 4 ), + 'add_object_page' => array( 4 ), + 'add_utility_page' => array( 4 ), + 'add_submenu_page' => array( 1, 5 ), + 'add_dashboard_page' => array( 4 ), + 'add_posts_page' => array( 4 ), + 'add_media_page' => array( 4 ), + 'add_links_page' => array( 4 ), + 'add_pages_page' => array( 4 ), + 'add_comments_page' => array( 4 ), + 'add_theme_page' => array( 4 ), + 'add_plugins_page' => array( 4 ), + 'add_users_page' => array( 4 ), + 'add_management_page' => array( 4 ), + 'add_options_page' => array( 4 ), + ); + + /** + * Process the parameters of a matched function. + * + * @since 0.11.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + foreach ( $this->target_functions[ $matched_content ] as $position ) { + if ( isset( $parameters[ $position ] ) ) { + $file_constant = $this->phpcsFile->findNext( \T_FILE, $parameters[ $position ]['start'], ( $parameters[ $position ]['end'] + 1 ) ); + + if ( false !== $file_constant ) { + $this->phpcsFile->addWarning( 'Using __FILE__ for menu slugs risks exposing filesystem structure.', $stackPtr, 'Using__FILE__' ); + } + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php new file mode 100644 index 000000000..2f6aa6a68 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/SafeRedirectSniff.php @@ -0,0 +1,48 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'wp_redirect' => array( + 'type' => 'warning', + 'message' => '%s() found. Using wp_safe_redirect(), along with the allowed_redirect_hosts filter if needed, can help avoid any chances of malicious redirects within code. It is also important to remember to call exit() after a redirect so that no other unwanted code is executed.', + 'functions' => array( + 'wp_redirect', + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php new file mode 100644 index 000000000..a545c5807 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php @@ -0,0 +1,233 @@ + array(), + 'unslashsanitize' => array(), + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_VARIABLE, + \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + + $superglobals = $this->input_superglobals; + + // Handling string interpolation. + if ( \T_DOUBLE_QUOTED_STRING === $this->tokens[ $stackPtr ]['code'] + || \T_HEREDOC === $this->tokens[ $stackPtr ]['code'] + ) { + $interpolated_variables = array_map( + function ( $symbol ) { + return '$' . $symbol; + }, + $this->get_interpolated_variables( $this->tokens[ $stackPtr ]['content'] ) + ); + foreach ( array_intersect( $interpolated_variables, $superglobals ) as $bad_variable ) { + $this->phpcsFile->addError( 'Detected usage of a non-sanitized, non-validated input variable %s: %s', $stackPtr, 'InputNotValidatedNotSanitized', array( $bad_variable, $this->tokens[ $stackPtr ]['content'] ) ); + } + + return; + } + + // Check if this is a superglobal. + if ( ! \in_array( $this->tokens[ $stackPtr ]['content'], $superglobals, true ) ) { + return; + } + + // If we're overriding a superglobal with an assignment, no need to test. + if ( $this->is_assignment( $stackPtr ) ) { + return; + } + + // This superglobal is being validated. + if ( $this->is_in_isset_or_empty( $stackPtr ) ) { + return; + } + + $array_keys = $this->get_array_access_keys( $stackPtr ); + + if ( empty( $array_keys ) ) { + return; + } + + $error_data = array( $this->tokens[ $stackPtr ]['content'] . '[' . implode( '][', $array_keys ) . ']' ); + + /* + * Check for validation first. + */ + $validated = false; + + for ( $i = ( $stackPtr + 1 ); $i < $this->phpcsFile->numTokens; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + if ( \T_OPEN_SQUARE_BRACKET === $this->tokens[ $i ]['code'] + && isset( $this->tokens[ $i ]['bracket_closer'] ) + ) { + // Skip over array keys. + $i = $this->tokens[ $i ]['bracket_closer']; + continue; + } + + if ( \T_COALESCE === $this->tokens[ $i ]['code'] ) { + $validated = true; + } + + // Anything else means this is not a validation coalesce. + break; + } + + if ( false === $validated ) { + $validated = $this->is_validated( $stackPtr, $array_keys, $this->check_validation_in_scope_only ); + } + + if ( false === $validated ) { + $this->phpcsFile->addError( + 'Detected usage of a possibly undefined superglobal array index: %s. Use isset() or empty() to check the index exists before using it', + $stackPtr, + 'InputNotValidated', + $error_data + ); + } + + if ( $this->has_whitelist_comment( 'sanitization', $stackPtr ) ) { + return; + } + + // If this variable is being tested with one of the `is_..()` functions, sanitization isn't needed. + if ( $this->is_in_type_test( $stackPtr ) ) { + return; + } + + // If this is a comparison ('a' == $_POST['foo']), sanitization isn't needed. + if ( $this->is_comparison( $stackPtr, false ) ) { + return; + } + + // If this is a comparison using the array comparison functions, sanitization isn't needed. + if ( $this->is_in_array_comparison( $stackPtr ) ) { + return; + } + + $this->mergeFunctionLists(); + + // Now look for sanitizing functions. + if ( ! $this->is_sanitized( $stackPtr, true ) ) { + $this->phpcsFile->addError( + 'Detected usage of a non-sanitized input variable: %s', + $stackPtr, + 'InputNotSanitized', + $error_data + ); + } + } + + /** + * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. + * + * @since 0.11.0 Split out from the `process()` method. + * + * @return void + */ + protected function mergeFunctionLists() { + if ( $this->customSanitizingFunctions !== $this->addedCustomFunctions['sanitize'] ) { + $this->sanitizingFunctions = $this->merge_custom_array( + $this->customSanitizingFunctions, + $this->sanitizingFunctions + ); + + $this->addedCustomFunctions['sanitize'] = $this->customSanitizingFunctions; + } + + if ( $this->customUnslashingSanitizingFunctions !== $this->addedCustomFunctions['unslashsanitize'] ) { + $this->unslashingSanitizingFunctions = $this->merge_custom_array( + $this->customUnslashingSanitizingFunctions, + $this->unslashingSanitizingFunctions + ); + + $this->addedCustomFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php new file mode 100644 index 000000000..e7090b481 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/Utils/I18nTextDomainFixerSniff.php @@ -0,0 +1,731 @@ + => + */ + protected $target_functions = array( + 'load_textdomain' => 1, + 'load_plugin_textdomain' => 1, + 'load_muplugin_textdomain' => 1, + 'load_theme_textdomain' => 1, + 'load_child_theme_textdomain' => 1, + 'unload_textdomain' => 1, + + '__' => 2, + '_e' => 2, + '_x' => 3, + '_ex' => 3, + '_n' => 4, + '_nx' => 5, + '_n_noop' => 3, + '_nx_noop' => 4, + 'translate_nooped_plural' => 3, + '_c' => 2, // Deprecated. + '_nc' => 4, // Deprecated. + '__ngettext' => 4, // Deprecated. + '__ngettext_noop' => 3, // Deprecated. + 'translate_with_context' => 2, // Deprecated. + + 'esc_html__' => 2, + 'esc_html_e' => 2, + 'esc_html_x' => 3, + 'esc_attr__' => 2, + 'esc_attr_e' => 2, + 'esc_attr_x' => 3, + + 'is_textdomain_loaded' => 1, + 'get_translations_for_domain' => 1, + + // Shouldn't be used by plugins/themes. + 'translate' => 2, + 'translate_with_gettext_context' => 3, + + // WP private functions. Shouldn't be used by plugins/themes. + '_load_textdomain_just_in_time' => 1, + '_get_path_to_translation_from_lang_dir' => 1, + '_get_path_to_translation' => 1, + ); + + /** + * Whether a valid new text domain was found. + * + * @since 1.2.0 + * + * @var bool + */ + private $is_valid = false; + + /** + * The new text domain as validated. + * + * @since 1.2.0 + * + * @var string + */ + private $validated_textdomain = ''; + + /** + * Whether the plugin/theme header has been seen and fixed yet. + * + * @since 1.2.0 + * + * @var bool + */ + private $header_found = false; + + /** + * Possible headers for a theme. + * + * @link https://developer.wordpress.org/themes/basics/main-stylesheet-style-css/ + * + * @since 1.2.0 + * + * @var array Array key is the header name, the value indicated whether it is a + * required (true) or optional (false) header. + */ + private $theme_headers = array( + 'Theme Name' => true, + 'Theme URI' => false, + 'Author' => true, + 'Author URI' => false, + 'Description' => true, + 'Version' => true, + 'License' => true, + 'License URI' => true, + 'Tags' => false, + 'Text Domain' => true, + 'Domain Path' => false, + ); + + /** + * Possible headers for a plugin. + * + * @link https://developer.wordpress.org/plugins/the-basics/header-requirements/ + * + * @since 1.2.0 + * + * @var array Array key is the header name, the value indicated whether it is a + * required (true) or optional (false) header. + */ + private $plugin_headers = array( + 'Plugin Name' => true, + 'Plugin URI' => false, + 'Description' => false, + 'Version' => false, + 'Author' => false, + 'Author URI' => false, + 'License' => false, + 'License URI' => false, + 'Text Domain' => false, + 'Domain Path' => false, + 'Network' => false, + ); + + /** + * Regex template to match theme/plugin headers. + * + * @since 1.2.0 + * + * @var string + */ + private $header_regex_template = '`^(?:\s*(?:(?:\*|//)\s*)?)?(%s)\s*:\s*([^\r\n]+)`'; + + /** + * Regex to match theme headers. + * + * Set from within the register() method. + * + * @since 1.2.0 + * + * @var string + */ + private $theme_header_regex; + + /** + * Regex to match plugin headers. + * + * Set from within the register() method. + * + * @since 1.2.0 + * + * @var string + */ + private $plugin_header_regex; + + /** + * The --tab-width CLI value that is being used. + * + * @since 1.2.0 + * + * @var integer + */ + private $tab_width = null; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 1.2.0 + * + * @return array + */ + public function register() { + $headers = array_map( + 'preg_quote', + array_keys( $this->theme_headers ), + array_fill( 0, \count( $this->theme_headers ), '`' ) + ); + $this->theme_header_regex = sprintf( $this->header_regex_template, implode( '|', $headers ) ); + + $headers = array_map( + 'preg_quote', + array_keys( $this->plugin_headers ), + array_fill( 0, \count( $this->plugin_headers ), '`' ) + ); + $this->plugin_header_regex = sprintf( $this->header_regex_template, implode( '|', $headers ) ); + + $targets = parent::register(); + + $targets[] = \T_DOC_COMMENT_OPEN_TAG; + $targets[] = \T_COMMENT; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + // Check if the old/new properties are correctly set. If not, bow out. + if ( ! is_string( $this->new_text_domain ) + || '' === $this->new_text_domain + ) { + return ( $this->phpcsFile->numTokens + 1 ); + } + + if ( isset( $this->old_text_domain ) ) { + $this->old_text_domain = $this->merge_custom_array( $this->old_text_domain, array(), false ); + + if ( ! is_array( $this->old_text_domain ) + || array() === $this->old_text_domain + ) { + return ( $this->phpcsFile->numTokens + 1 ); + } + } + + // Only validate and throw warning about the text domain once. + if ( $this->new_text_domain !== $this->validated_textdomain ) { + $this->is_valid = false; + $this->validated_textdomain = $this->new_text_domain; + $this->header_found = false; + + if ( 'default' === $this->new_text_domain ) { + $this->phpcsFile->addWarning( + 'The "default" text domain is reserved for WordPress core use and should not be used by plugins or themes', + 0, + 'ReservedNewDomain', + array( $this->new_text_domain ) + ); + + return ( $this->phpcsFile->numTokens + 1 ); + } + + if ( preg_match( '`^[a-z0-9-]+$`', $this->new_text_domain ) !== 1 ) { + $this->phpcsFile->addWarning( + 'The text domain should be a simple lowercase text string with words separated by dashes. "%s" appears invalid', + 0, + 'InvalidNewDomain', + array( $this->new_text_domain ) + ); + + return ( $this->phpcsFile->numTokens + 1 ); + } + + // If the text domain passed both validations, it should be considered valid. + $this->is_valid = true; + + } elseif ( false === $this->is_valid ) { + return ( $this->phpcsFile->numTokens + 1 ); + } + + if ( isset( $this->tab_width ) === false ) { + if ( isset( $this->phpcsFile->config->tabWidth ) === false + || 0 === $this->phpcsFile->config->tabWidth + ) { + // We have no idea how wide tabs are, so assume 4 spaces for fixing. + $this->tab_width = 4; + } else { + $this->tab_width = $this->phpcsFile->config->tabWidth; + } + } + + if ( \T_DOC_COMMENT_OPEN_TAG === $this->tokens[ $stackPtr ]['code'] + || \T_COMMENT === $this->tokens[ $stackPtr ]['code'] + ) { + // Examine for plugin/theme file header. + return $this->process_comments( $stackPtr ); + + } elseif ( 'CSS' !== $this->phpcsFile->tokenizerType ) { + // Examine a T_STRING token in a PHP file as a function call. + return parent::process_token( $stackPtr ); + } + } + + + /** + * Process the parameters of a matched function. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $target_param = $this->target_functions[ $matched_content ]; + + if ( isset( $parameters[ $target_param ] ) === false && 1 !== $target_param ) { + $error_msg = 'Missing $domain arg'; + $error_code = 'MissingArgDomain'; + + if ( isset( $parameters[ ( $target_param - 1 ) ] ) ) { + $fix = $this->phpcsFile->addFixableError( $error_msg, $stackPtr, $error_code ); + + if ( true === $fix ) { + $start_previous = $parameters[ ( $target_param - 1 ) ]['start']; + $end_previous = $parameters[ ( $target_param - 1 ) ]['end']; + if ( \T_WHITESPACE === $this->tokens[ $start_previous ]['code'] + && $this->tokens[ $start_previous ]['content'] === $this->phpcsFile->eolChar + ) { + // Replicate the new line + indentation of the previous item. + $replacement = ','; + for ( $i = $start_previous; $i <= $end_previous; $i++ ) { + if ( \T_WHITESPACE !== $this->tokens[ $i ]['code'] ) { + break; + } + + if ( isset( $this->tokens[ $i ]['orig_content'] ) ) { + $replacement .= $this->tokens[ $i ]['orig_content']; + } else { + $replacement .= $this->tokens[ $i ]['content']; + } + } + + $replacement .= "'{$this->new_text_domain}'"; + } else { + $replacement = ", '{$this->new_text_domain}'"; + } + + if ( \T_WHITESPACE === $this->tokens[ $end_previous ]['code'] ) { + $this->phpcsFile->fixer->addContentBefore( $end_previous, $replacement ); + } else { + $this->phpcsFile->fixer->addContent( $end_previous, $replacement ); + } + } + } else { + $error_msg .= ' and preceding argument(s)'; + $error_code = 'MissingArgs'; + + // Expected preceeding param also missing, just throw the warning. + $this->phpcsFile->addWarning( $error_msg, $stackPtr, $error_code ); + } + + return; + } + + // Target parameter found. Let's examine it. + $domain_param_start = $parameters[ $target_param ]['start']; + $domain_param_end = $parameters[ $target_param ]['end']; + $domain_token = null; + + for ( $i = $domain_param_start; $i <= $domain_param_end; $i++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) ) { + continue; + } + + if ( \T_CONSTANT_ENCAPSED_STRING !== $this->tokens[ $i ]['code'] ) { + // Unexpected token found, not our concern. This is handled by the I18n sniff. + return; + } + + if ( isset( $domain_token ) ) { + // More than one T_CONSTANT_ENCAPSED_STRING found, not our concern. This is handled by the I18n sniff. + return; + } + + $domain_token = $i; + } + + // If we're still here, this means only one T_CONSTANT_ENCAPSED_STRING was found. + $old_domain = $this->strip_quotes( $this->tokens[ $domain_token ]['content'] ); + + if ( ! \in_array( $old_domain, $this->old_text_domain, true ) ) { + // Not a text domain targetted for replacement, ignore. + return; + } + + $fix = $this->phpcsFile->addFixableError( + 'Mismatched text domain. Expected \'%s\' but found \'%s\'', + $domain_token, + 'TextDomainMismatch', + array( $this->new_text_domain, $old_domain ) + ); + + if ( true === $fix ) { + $replacement = str_replace( $old_domain, $this->new_text_domain, $this->tokens[ $domain_token ]['content'] ); + $this->phpcsFile->fixer->replaceToken( $domain_token, $replacement ); + } + } + + /** + * Process the function if no parameters were found. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return void + */ + public function process_no_parameters( $stackPtr, $group_name, $matched_content ) { + + $target_param = $this->target_functions[ $matched_content ]; + + if ( 1 !== $target_param ) { + // Only process the no param case as fixable if the text domain is expected to be the first parameter. + $this->phpcsFile->addWarning( 'Missing $domain arg and preceding argument(s)', $stackPtr, 'MissingArgs' ); + return; + } + + $opener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $opener ]['code'] + || isset( $this->tokens[ $opener ]['parenthesis_closer'] ) === false + ) { + // Parse error or live coding. + return; + } + + $fix = $this->phpcsFile->addFixableError( 'Missing $domain arg', $stackPtr, 'MissingArgDomain' ); + if ( true === $fix ) { + $closer = $this->tokens[ $opener ]['parenthesis_closer']; + $replacement = " '{$this->new_text_domain}' "; + + if ( $this->tokens[ $opener ]['line'] !== $this->tokens[ $closer ]['line'] ) { + $replacement = trim( $replacement ); + $addBefore = ( $closer - 1 ); + if ( \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] + && $this->tokens[ $closer - 1 ]['line'] === $this->tokens[ $closer ]['line'] + ) { + if ( isset( $this->tokens[ ( $closer - 1 ) ]['orig_content'] ) ) { + $replacement = $this->tokens[ ( $closer - 1 ) ]['orig_content'] + . "\t" + . $replacement; + } else { + $replacement = $this->tokens[ ( $closer - 1 ) ]['content'] + . str_repeat( ' ', $this->tab_width ) + . $replacement; + } + + --$addBefore; + } else { + // We don't know whether the code uses tabs or spaces, so presume WPCS, i.e. tabs. + $replacement = "\t" . $replacement; + } + + $replacement = $this->phpcsFile->eolChar . $replacement; + + $this->phpcsFile->fixer->addContentBefore( $addBefore, $replacement ); + + } elseif ( \T_WHITESPACE === $this->tokens[ ( $closer - 1 ) ]['code'] ) { + $this->phpcsFile->fixer->replaceToken( ( $closer - 1 ), $replacement ); + } else { + $this->phpcsFile->fixer->addContentBefore( $closer, $replacement ); + } + } + } + + + /** + * Process comments to find the plugin/theme headers. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_comments( $stackPtr ) { + if ( true === $this->header_found && ! defined( 'PHP_CODESNIFFER_IN_TESTS' ) ) { + return; + } + + $regex = $this->plugin_header_regex; + $headers = $this->plugin_headers; + $type = 'plugin'; + $skip_to = $stackPtr; + + $file = $this->strip_quotes( $this->phpcsFile->getFileName() ); + if ( 'STDIN' === $file ) { + return; + } + + $file_name = basename( $file ); + if ( 'CSS' === $this->phpcsFile->tokenizerType ) { + if ( 'style.css' !== $file_name && ! defined( 'PHP_CODESNIFFER_IN_TESTS' ) ) { + // CSS files only need to be examined for the file header. + return ( $this->phpcsFile->numTokens + 1 ); + } + + $regex = $this->theme_header_regex; + $headers = $this->theme_headers; + $type = 'theme'; + } + + $comment_details = array( + 'required_header_found' => false, + 'headers_found' => 0, + 'text_domain_ptr' => false, + 'text_domain_found' => '', + 'last_header_ptr' => false, + 'last_header_matches' => array(), + ); + + if ( \T_COMMENT === $this->tokens[ $stackPtr ]['code'] ) { + $block_comment = false; + if ( substr( $this->tokens[ $stackPtr ]['content'], 0, 2 ) === '/*' ) { + $block_comment = true; + } + + $current = $stackPtr; + do { + if ( false === $comment_details['text_domain_ptr'] + || false === $comment_details['required_header_found'] + || $comment_details['headers_found'] < 3 + ) { + $comment_details = $this->examine_comment_line( $current, $regex, $headers, $comment_details ); + } + + if ( true === $block_comment && substr( $this->tokens[ $current ]['content'], -2 ) === '*/' ) { + ++$current; + break; + } + + ++$current; + } while ( isset( $this->tokens[ $current ] ) && \T_COMMENT === $this->tokens[ $current ]['code'] ); + + $skip_to = $current; + + } else { + if ( ! isset( $this->tokens[ $stackPtr ]['comment_closer'] ) ) { + return; + } + + $closer = $this->tokens[ $stackPtr ]['comment_closer']; + $current = $stackPtr; + + while ( ( $current = $this->phpcsFile->findNext( \T_DOC_COMMENT_STRING, ( $current + 1 ), $closer ) ) !== false ) { + $comment_details = $this->examine_comment_line( $current, $regex, $headers, $comment_details ); + + if ( false !== $comment_details['text_domain_ptr'] + && true === $comment_details['required_header_found'] + && $comment_details['headers_found'] >= 3 + ) { + // No need to look at the rest of the docblock. + break; + } + } + + $skip_to = $closer; + } + + // So, was this the plugin/theme header ? + if ( true === $comment_details['required_header_found'] + && $comment_details['headers_found'] >= 3 + ) { + $this->header_found = true; + + $text_domain_ptr = $comment_details['text_domain_ptr']; + $text_domain_found = $comment_details['text_domain_found']; + + if ( false !== $text_domain_ptr ) { + if ( $this->new_text_domain !== $text_domain_found + && ( \in_array( $text_domain_found, $this->old_text_domain, true ) ) + ) { + $fix = $this->phpcsFile->addFixableError( + 'Mismatched text domain in %s header. Expected \'%s\' but found \'%s\'', + $text_domain_ptr, + 'TextDomainHeaderMismatch', + array( + $type, + $this->new_text_domain, + $text_domain_found, + ) + ); + + if ( true === $fix ) { + if ( isset( $this->tokens[ $text_domain_ptr ]['orig_content'] ) ) { + $replacement = $this->tokens[ $text_domain_ptr ]['orig_content']; + } else { + $replacement = $this->tokens[ $text_domain_ptr ]['content']; + } + + $replacement = str_replace( $text_domain_found, $this->new_text_domain, $replacement ); + + $this->phpcsFile->fixer->replaceToken( $text_domain_ptr, $replacement ); + } + } + } else { + $last_header_ptr = $comment_details['last_header_ptr']; + $last_header_matches = $comment_details['last_header_matches']; + + $fix = $this->phpcsFile->addFixableError( + 'Missing "Text Domain" in %s header', + $last_header_ptr, + 'MissingTextDomainHeader', + array( $type ) + ); + + if ( true === $fix ) { + if ( isset( $this->tokens[ $last_header_ptr ]['orig_content'] ) ) { + $replacement = $this->tokens[ $last_header_ptr ]['orig_content']; + } else { + $replacement = $this->tokens[ $last_header_ptr ]['content']; + } + + $replacement = str_replace( $last_header_matches[1], 'Text Domain', $replacement ); + $replacement = str_replace( $last_header_matches[2], $this->new_text_domain, $replacement ); + + if ( \T_DOC_COMMENT_OPEN_TAG === $this->tokens[ $stackPtr ]['code'] ) { + for ( $i = ( $last_header_ptr - 1 ); ; $i-- ) { + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $last_header_ptr ]['line'] ) { + ++$i; + break; + } + } + + $replacement = $this->phpcsFile->eolChar + . $this->phpcsFile->getTokensAsString( $i, ( $last_header_ptr - $i ), true ) + . $replacement; + } + + $this->phpcsFile->fixer->addContent( $comment_details['last_header_ptr'], $replacement ); + } + } + } + + return $skip_to; + } + + /** + * Examine an individual token in a larger comment for plugin/theme headers. + * + * @since 1.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $regex The regex to use to examine the comment line. + * @param array $headers Valid headers for a plugin or theme. + * @param array $comment_details The information collected so far. + * + * @return array Adjusted $comment_details array + */ + protected function examine_comment_line( $stackPtr, $regex, $headers, $comment_details ) { + if ( preg_match( $regex, $this->tokens[ $stackPtr ]['content'], $matches ) === 1 ) { + ++$comment_details['headers_found']; + + if ( true === $headers[ $matches[1] ] ) { + $comment_details['required_header_found'] = true; + } + + if ( 'Text Domain' === $matches[1] ) { + $comment_details['text_domain_ptr'] = $stackPtr; + $comment_details['text_domain_found'] = trim( $matches[2] ); + } + + $comment_details['last_header_ptr'] = $stackPtr; + $comment_details['last_header_matches'] = $matches; + } + + return $comment_details; + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php new file mode 100644 index 000000000..fc6e8fbbb --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/AlternativeFunctionsSniff.php @@ -0,0 +1,316 @@ + true, + 'php://output' => true, + 'php://stdin' => true, + 'php://stdout' => true, + 'php://stderr' => true, + ); + + /** + * Local input streams which should not be flagged for the file system function checks if + * the $filename starts with them. + * + * @link http://php.net/manual/en/wrappers.php.php + * + * @var array + */ + protected $allowed_local_stream_partials = array( + 'php://temp/', + 'php://fd/', + ); + + /** + * Local input stream constants which should not be flagged for the file system function checks. + * + * @link http://php.net/manual/en/wrappers.php.php + * + * @var array + */ + protected $allowed_local_stream_constants = array( + 'STDIN' => true, + 'STDOUT' => true, + 'STDERR' => true, + ); + + /** + * Groups of functions to restrict. + * + * Example: groups => array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'since' => '4.9.0', //=> the WP version in which the alternative became available. + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'curl' => array( + 'type' => 'warning', + 'message' => 'Using cURL functions is highly discouraged. Use wp_remote_get() instead.', + 'since' => '2.7.0', + 'functions' => array( + 'curl_*', + ), + 'whitelist' => array( + 'curl_version' => true, + ), + ), + + 'parse_url' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged because of inconsistency in the output across PHP versions; use wp_parse_url() instead.', + 'since' => '4.4.0', + 'functions' => array( + 'parse_url', + ), + ), + + 'json_encode' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use wp_json_encode() instead.', + 'since' => '4.1.0', + 'functions' => array( + 'json_encode', + ), + ), + + 'file_get_contents' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use wp_remote_get() for remote URLs instead.', + 'since' => '2.7.0', + 'functions' => array( + 'file_get_contents', + ), + ), + + 'file_system_read' => array( + 'type' => 'warning', + 'message' => 'File operations should use WP_Filesystem methods instead of direct PHP filesystem calls. Found: %s()', + 'since' => '2.5.0', + 'functions' => array( + 'readfile', + 'fclose', + 'fopen', + 'fread', + 'fwrite', + 'file_put_contents', + 'fsockopen', + 'pfsockopen', + ), + ), + + 'strip_tags' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use the more comprehensive wp_strip_all_tags() instead.', + 'since' => '2.9.0', + 'functions' => array( + 'strip_tags', + ), + ), + + 'rand_seeding' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Rand seeding is not necessary when using the wp_rand() function (as you should).', + 'since' => '2.6.2', + 'functions' => array( + 'srand', + 'mt_srand', + ), + ), + + 'rand' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use the far less predictable wp_rand() instead.', + 'since' => '2.6.2', + 'functions' => array( + 'rand', + 'mt_rand', + ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->get_wp_version_from_cl(); + + /* + * Deal with exceptions. + */ + switch ( $matched_content ) { + case 'strip_tags': + /* + * The function `wp_strip_all_tags()` is only a valid alternative when + * only the first parameter is passed to `strip_tags()`. + */ + if ( $this->get_function_call_parameter_count( $stackPtr ) !== 1 ) { + return; + } + + break; + + case 'wp_parse_url': + /* + * Before WP 4.7.0, the function `wp_parse_url()` was only a valid alternative + * if no second param was passed to `parse_url()`. + * + * @see https://developer.wordpress.org/reference/functions/wp_parse_url/#changelog + */ + if ( $this->get_function_call_parameter_count( $stackPtr ) !== 1 + && version_compare( $this->minimum_supported_version, '4.7.0', '<' ) + ) { + return; + } + + break; + + case 'file_get_contents': + /* + * Using `wp_remote_get()` will only work for remote URLs. + * See if we can determine is this function call is for a local file and if so, bow out. + */ + $params = $this->get_function_call_parameters( $stackPtr ); + + if ( isset( $params[2] ) && 'true' === $params[2]['raw'] ) { + // Setting `$use_include_path` to `true` is only relevant for local files. + return; + } + + if ( isset( $params[1] ) === false ) { + // If the file to get is not set, this is a non-issue anyway. + return; + } + + if ( strpos( $params[1]['raw'], 'http:' ) !== false + || strpos( $params[1]['raw'], 'https:' ) !== false + ) { + // Definitely a URL, throw notice. + break; + } + + if ( preg_match( '`\b(?:ABSPATH|WP_(?:CONTENT|PLUGIN)_DIR|WPMU_PLUGIN_DIR|TEMPLATEPATH|STYLESHEETPATH|(?:MU)?PLUGINDIR)\b`', $params[1]['raw'] ) === 1 ) { + // Using any of the constants matched in this regex is an indicator of a local file. + return; + } + + if ( preg_match( '`(?:get_home_path|plugin_dir_path|get_(?:stylesheet|template)_directory|wp_upload_dir)\s*\(`i', $params[1]['raw'] ) === 1 ) { + // Using any of the functions matched in the regex is an indicator of a local file. + return; + } + + if ( $this->is_local_data_stream( $params[1]['raw'] ) === true ) { + // Local data stream. + return; + } + + unset( $params ); + + break; + + case 'readfile': + case 'fopen': + case 'file_put_contents': + /* + * Allow for handling raw data streams from the request body. + */ + $first_param = $this->get_function_call_parameter( $stackPtr, 1 ); + + if ( false === $first_param ) { + // If the file to work with is not set, local data streams don't come into play. + break; + } + + if ( $this->is_local_data_stream( $first_param['raw'] ) === true ) { + // Local data stream. + return; + } + + unset( $first_param ); + + break; + } + + if ( ! isset( $this->groups[ $group_name ]['since'] ) ) { + return parent::process_matched_token( $stackPtr, $group_name, $matched_content ); + } + + // Verify if the alternative is available in the minimum supported WP version. + if ( version_compare( $this->groups[ $group_name ]['since'], $this->minimum_supported_version, '<=' ) ) { + return parent::process_matched_token( $stackPtr, $group_name, $matched_content ); + } + } + + /** + * Determine based on the "raw" parameter value, whether a file parameter points to + * a local data stream. + * + * @param string $raw_param_value Raw parameter value. + * + * @return bool True if this is a local data stream. False otherwise. + */ + protected function is_local_data_stream( $raw_param_value ) { + + $raw_stripped = $this->strip_quotes( $raw_param_value ); + if ( isset( $this->allowed_local_streams[ $raw_stripped ] ) + || isset( $this->allowed_local_stream_constants[ $raw_param_value ] ) + ) { + return true; + } + + foreach ( $this->allowed_local_stream_partials as $partial ) { + if ( strpos( $raw_stripped, $partial ) === 0 ) { + return true; + } + } + + return false; + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php new file mode 100644 index 000000000..bf98233fb --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CapitalPDangitSniff.php @@ -0,0 +1,292 @@ +\'"()]*?\.(?:php|js|css|png|j[e]?pg|gif|pot))#i'; + + /** + * Regex to match a large number or spelling variations of WordPress in class names. + * + * @var string + */ + const WP_CLASSNAME_REGEX = '`(?:^|_)(Word[_]*Pres+)(?:_|$)`i'; + + /** + * String tokens we want to listen for. + * + * @var array + */ + private $text_string_tokens = array( + \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING => \T_DOUBLE_QUOTED_STRING, + \T_HEREDOC => \T_HEREDOC, + \T_NOWDOC => \T_NOWDOC, + \T_INLINE_HTML => \T_INLINE_HTML, + ); + + /** + * Comment tokens we want to listen for as they contain text strings. + * + * @var array + */ + private $comment_text_tokens = array( + \T_DOC_COMMENT => \T_DOC_COMMENT, + \T_DOC_COMMENT_STRING => \T_DOC_COMMENT_STRING, + \T_COMMENT => \T_COMMENT, + ); + + /** + * Combined text string and comment tokens array. + * + * This property is set in the register() method and used for lookups. + * + * @var array + */ + private $text_and_comment_tokens = array(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.12.0 + * + * @return array + */ + public function register() { + // Union the arrays - keeps the array keys. + $this->text_and_comment_tokens = ( $this->text_string_tokens + $this->comment_text_tokens ); + + $targets = ( $this->text_and_comment_tokens + Tokens::$ooScopeTokens ); + + // Also sniff for array tokens to make skipping anything within those more efficient. + $targets[ \T_ARRAY ] = \T_ARRAY; + $targets[ \T_OPEN_SHORT_ARRAY ] = \T_OPEN_SHORT_ARRAY; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + if ( $this->has_whitelist_comment( 'spelling', $stackPtr ) ) { + return; + } + + /* + * Ignore tokens within an array definition as this is a false positive in 80% of all cases. + * + * The return values skip to the end of the array. + * This prevents the sniff "hanging" on very long configuration arrays. + */ + if ( \T_OPEN_SHORT_ARRAY === $this->tokens[ $stackPtr ]['code'] && isset( $this->tokens[ $stackPtr ]['bracket_closer'] ) ) { + return $this->tokens[ $stackPtr ]['bracket_closer']; + } elseif ( \T_ARRAY === $this->tokens[ $stackPtr ]['code'] && isset( $this->tokens[ $stackPtr ]['parenthesis_closer'] ) ) { + return $this->tokens[ $stackPtr ]['parenthesis_closer']; + } + + /* + * Deal with misspellings in class/interface/trait names. + * These are not auto-fixable, but need the attention of a developer. + */ + if ( isset( Tokens::$ooScopeTokens[ $this->tokens[ $stackPtr ]['code'] ] ) ) { + $classname = $this->phpcsFile->getDeclarationName( $stackPtr ); + if ( empty( $classname ) ) { + return; + } + + if ( preg_match_all( self::WP_CLASSNAME_REGEX, $classname, $matches, \PREG_PATTERN_ORDER ) > 0 ) { + $mispelled = $this->retrieve_misspellings( $matches[1] ); + + if ( ! empty( $mispelled ) ) { + $this->phpcsFile->addWarning( + 'Please spell "WordPress" correctly. Found: "%s" as part of the class/interface/trait name.', + $stackPtr, + 'MisspelledClassName', + array( implode( ', ', $mispelled ) ) + ); + } + } + + return; + } + + /* + * Deal with misspellings in text strings and documentation. + */ + + // Ignore content of docblock @link tags. + if ( \T_DOC_COMMENT_STRING === $this->tokens[ $stackPtr ]['code'] + || \T_DOC_COMMENT === $this->tokens[ $stackPtr ]['code'] + ) { + + $comment_start = $this->phpcsFile->findPrevious( \T_DOC_COMMENT_OPEN_TAG, ( $stackPtr - 1 ) ); + if ( false !== $comment_start ) { + $comment_tag = $this->phpcsFile->findPrevious( \T_DOC_COMMENT_TAG, ( $stackPtr - 1 ), $comment_start ); + if ( false !== $comment_tag && '@link' === $this->tokens[ $comment_tag ]['content'] ) { + // @link tag, so ignore. + return; + } + } + } + + // Ignore any text strings which are array keys `$var['key']` as this is a false positive in 80% of all cases. + if ( \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $stackPtr ]['code'] ) { + $prevToken = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true, null, true ); + if ( false !== $prevToken && \T_OPEN_SQUARE_BRACKET === $this->tokens[ $prevToken ]['code'] ) { + $nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true, null, true ); + if ( false !== $nextToken && \T_CLOSE_SQUARE_BRACKET === $this->tokens[ $nextToken ]['code'] ) { + return; + } + } + } + + // Ignore constant declarations via define(). + if ( $this->is_in_function_call( $stackPtr, array( 'define' => true ), true, true ) ) { + return; + } + + // Ignore constant declarations using the const keyword. + $stop_points = array( + \T_CONST, + \T_SEMICOLON, + \T_OPEN_TAG, + \T_CLOSE_TAG, + \T_OPEN_CURLY_BRACKET, + ); + $maybe_const = $this->phpcsFile->findPrevious( $stop_points, ( $stackPtr - 1 ) ); + if ( false !== $maybe_const && \T_CONST === $this->tokens[ $maybe_const ]['code'] ) { + return; + } + + $content = $this->tokens[ $stackPtr ]['content']; + + if ( preg_match_all( self::WP_REGEX, $content, $matches, ( \PREG_PATTERN_ORDER | \PREG_OFFSET_CAPTURE ) ) > 0 ) { + /* + * Prevent some typical false positives. + */ + if ( isset( $this->text_and_comment_tokens[ $this->tokens[ $stackPtr ]['code'] ] ) ) { + $offset = 0; + foreach ( $matches[1] as $key => $match_data ) { + $next_offset = ( $match_data[1] + \strlen( $match_data[0] ) ); + + // Prevent matches on part of a URL. + if ( preg_match( '`http[s]?://[^\s<>\'"()]*' . preg_quote( $match_data[0], '`' ) . '`', $content, $discard, 0, $offset ) === 1 ) { + unset( $matches[1][ $key ] ); + } elseif ( preg_match( '`[a-z]+=(["\'])' . preg_quote( $match_data[0], '`' ) . '\1`', $content, $discard, 0, $offset ) === 1 ) { + // Prevent matches on html attributes like: `value="wordpress"`. + unset( $matches[1][ $key ] ); + } elseif ( preg_match( '`\\\\\'' . preg_quote( $match_data[0], '`' ) . '\\\\\'`', $content, $discard, 0, $offset ) === 1 ) { + // Prevent matches on xpath queries and such: `\'wordpress\'`. + unset( $matches[1][ $key ] ); + } elseif ( preg_match( '`(?:\?|&|&)[a-z0-9_]+=' . preg_quote( $match_data[0], '`' ) . '(?:&|$)`', $content, $discard, 0, $offset ) === 1 ) { + // Prevent matches on url query strings: `?something=wordpress`. + unset( $matches[1][ $key ] ); + } + + $offset = $next_offset; + } + + if ( empty( $matches[1] ) ) { + return; + } + } + + $mispelled = $this->retrieve_misspellings( $matches[1] ); + + if ( empty( $mispelled ) ) { + return; + } + + $fix = $this->phpcsFile->addFixableWarning( + 'Please spell "WordPress" correctly. Found %s misspelling(s): %s', + $stackPtr, + 'Misspelled', + array( + \count( $mispelled ), + implode( ', ', $mispelled ), + ) + ); + + if ( true === $fix ) { + // Apply fixes based on offset to ensure we don't replace false positives. + $replacement = $content; + foreach ( $matches[1] as $match ) { + $replacement = substr_replace( $replacement, 'WordPress', $match[1], \strlen( $match[0] ) ); + } + + $this->phpcsFile->fixer->replaceToken( $stackPtr, $replacement ); + } + } + } + + /** + * Retrieve a list of misspellings based on an array of matched variations on the target word. + * + * @param array $match_stack Array of matched variations of the target word. + * @return array Array containing only the misspelled variants. + */ + protected function retrieve_misspellings( $match_stack ) { + $mispelled = array(); + foreach ( $match_stack as $match ) { + // Deal with multi-dimensional arrays when capturing offset. + if ( \is_array( $match ) ) { + $match = $match[0]; + } + + if ( 'WordPress' !== $match ) { + $mispelled[] = $match; + } + } + + return $mispelled; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php new file mode 100644 index 000000000..7cfdddd91 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/CronIntervalSniff.php @@ -0,0 +1,235 @@ + 60, + 'HOUR_IN_SECONDS' => 3600, + 'DAY_IN_SECONDS' => 86400, + 'WEEK_IN_SECONDS' => 604800, + 'MONTH_IN_SECONDS' => 2592000, + 'YEAR_IN_SECONDS' => 31536000, + ); + + /** + * Function within which the hook should be found. + * + * @var array + */ + protected $valid_functions = array( + 'add_filter' => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_CONSTANT_ENCAPSED_STRING, + \T_DOUBLE_QUOTED_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + $token = $this->tokens[ $stackPtr ]; + + if ( 'cron_schedules' !== $this->strip_quotes( $token['content'] ) ) { + return; + } + + // If within add_filter. + $functionPtr = $this->is_in_function_call( $stackPtr, $this->valid_functions ); + if ( false === $functionPtr ) { + return; + } + + $callback = $this->get_function_call_parameter( $functionPtr, 2 ); + if ( false === $callback ) { + return; + } + + if ( $stackPtr >= $callback['start'] ) { + // "cron_schedules" found in the second parameter, not the first. + return; + } + + // Detect callback function name. + $callbackArrayPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, $callback['start'], ( $callback['end'] + 1 ), true ); + + // If callback is array, get second element. + if ( false !== $callbackArrayPtr + && ( \T_ARRAY === $this->tokens[ $callbackArrayPtr ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $callbackArrayPtr ]['code'] ) + ) { + $callback = $this->get_function_call_parameter( $callbackArrayPtr, 2 ); + + if ( false === $callback ) { + $this->confused( $stackPtr ); + return; + } + } + + unset( $functionPtr ); + + // Search for the function in tokens. + $callbackFunctionPtr = $this->phpcsFile->findNext( array( \T_CONSTANT_ENCAPSED_STRING, \T_DOUBLE_QUOTED_STRING, \T_CLOSURE ), $callback['start'], ( $callback['end'] + 1 ) ); + + if ( false === $callbackFunctionPtr ) { + $this->confused( $stackPtr ); + return; + } + + if ( \T_CLOSURE === $this->tokens[ $callbackFunctionPtr ]['code'] ) { + $functionPtr = $callbackFunctionPtr; + } else { + $functionName = $this->strip_quotes( $this->tokens[ $callbackFunctionPtr ]['content'] ); + + for ( $ptr = 0; $ptr < $this->phpcsFile->numTokens; $ptr++ ) { + if ( \T_FUNCTION === $this->tokens[ $ptr ]['code'] ) { + $foundName = $this->phpcsFile->getDeclarationName( $ptr ); + if ( $foundName === $functionName ) { + $functionPtr = $ptr; + break; + } elseif ( isset( $this->tokens[ $ptr ]['scope_closer'] ) ) { + // Skip to the end of the function definition. + $ptr = $this->tokens[ $ptr ]['scope_closer']; + } + } + } + } + + if ( ! isset( $functionPtr ) ) { + $this->confused( $stackPtr ); + return; + } + + if ( ! isset( $this->tokens[ $functionPtr ]['scope_opener'], $this->tokens[ $functionPtr ]['scope_closer'] ) ) { + return; + } + + $opening = $this->tokens[ $functionPtr ]['scope_opener']; + $closing = $this->tokens[ $functionPtr ]['scope_closer']; + for ( $i = $opening; $i <= $closing; $i++ ) { + + if ( \in_array( $this->tokens[ $i ]['code'], array( \T_CONSTANT_ENCAPSED_STRING, \T_DOUBLE_QUOTED_STRING ), true ) ) { + if ( 'interval' === $this->strip_quotes( $this->tokens[ $i ]['content'] ) ) { + $operator = $this->phpcsFile->findNext( \T_DOUBLE_ARROW, $i, null, false, null, true ); + if ( false === $operator ) { + $this->confused( $stackPtr ); + return; + } + + $valueStart = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $operator + 1 ), null, true, null, true ); + $valueEnd = $this->phpcsFile->findNext( array( \T_COMMA, \T_CLOSE_PARENTHESIS ), ( $valueStart + 1 ) ); + $value = ''; + for ( $j = $valueStart; $j < $valueEnd; $j++ ) { + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $j ]['code'] ] ) ) { + continue; + } + $value .= $this->tokens[ $j ]['content']; + } + + if ( is_numeric( $value ) ) { + $interval = $value; + break; + } + + // Deal correctly with WP time constants. + $value = str_replace( array_keys( $this->wp_time_constants ), array_values( $this->wp_time_constants ), $value ); + + // If all digits and operators, eval! + if ( preg_match( '#^[\s\d+*/-]+$#', $value ) > 0 ) { + $interval = eval( "return ( $value );" ); // phpcs:ignore Squiz.PHP.Eval -- No harm here. + break; + } + + $this->confused( $stackPtr ); + return; + } + } + } + + $this->min_interval = (int) $this->min_interval; + + if ( isset( $interval ) && $interval < $this->min_interval ) { + $minutes = round( ( $this->min_interval / 60 ), 1 ); + $this->phpcsFile->addWarning( + 'Scheduling crons at %s sec ( less than %s minutes ) is discouraged.', + $stackPtr, + 'CronSchedulesInterval', + array( + $interval, + $minutes, + ) + ); + return; + } + } + + /** + * Add warning about unclear cron schedule change. + * + * @param int $stackPtr The position of the current token in the stack. + */ + public function confused( $stackPtr ) { + $this->phpcsFile->addWarning( + 'Detected changing of cron_schedules, but could not detect the interval value.', + $stackPtr, + 'ChangeDetected' + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php new file mode 100644 index 000000000..9d1f95bff --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedClassesSniff.php @@ -0,0 +1,120 @@ + value + * in a custom ruleset. + * + * @uses \WordPressCS\WordPress\Sniff::$minimum_supported_version + */ +class DeprecatedClassesSniff extends AbstractClassRestrictionsSniff { + + /** + * List of deprecated classes with alternative when available. + * + * To be updated after every major release. + * + * Version numbers should be fully qualified. + * + * @var array + */ + private $deprecated_classes = array( + + // WP 3.1.0. + 'WP_User_Search' => array( + 'alt' => 'WP_User_Query', + 'version' => '3.1.0', + ), + + // WP 4.9.0. + 'Customize_New_Menu_Section' => array( + 'version' => '4.9.0', + ), + 'WP_Customize_New_Menu_Control' => array( + 'version' => '4.9.0', + ), + + // WP 5.3.0. + 'Services_JSON' => array( + 'alt' => 'The PHP native JSON extension', + 'version' => '5.3.0', + ), + ); + + + /** + * Groups of classes to restrict. + * + * @return array + */ + public function getGroups() { + // Make sure all array keys are lowercase. + $this->deprecated_classes = array_change_key_case( $this->deprecated_classes, CASE_LOWER ); + + return array( + 'deprecated_classes' => array( + 'classes' => array_keys( $this->deprecated_classes ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. Will + * always be 'deprecated_classes'. + * @param string $matched_content The token content (class name) which was matched. + * + * @return void + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->get_wp_version_from_cl(); + + $class_name = ltrim( strtolower( $matched_content ), '\\' ); + + $message = 'The %s class has been deprecated since WordPress version %s.'; + $data = array( + ltrim( $matched_content, '\\' ), + $this->deprecated_classes[ $class_name ]['version'], + ); + + if ( ! empty( $this->deprecated_classes[ $class_name ]['alt'] ) ) { + $message .= ' Use %s instead.'; + $data[] = $this->deprecated_classes[ $class_name ]['alt']; + } + + $this->addMessage( + $message, + $stackPtr, + ( version_compare( $this->deprecated_classes[ $class_name ]['version'], $this->minimum_supported_version, '<' ) ), + $this->string_to_errorcode( $class_name . 'Found' ), + $data + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php new file mode 100644 index 000000000..df7a4b552 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php @@ -0,0 +1,1422 @@ + value + * in a custom ruleset. + * + * @uses \WordPressCS\WordPress\Sniff::$minimum_supported_version + */ +class DeprecatedFunctionsSniff extends AbstractFunctionRestrictionsSniff { + + /** + * List of deprecated functions with alternative when available. + * + * To be updated after every major release. + * Last updated for WordPress 4.8. + * + * Version numbers should be fully qualified. + * Replacement functions should have parentheses. + * + * To retrieve a function list for comparison, the following tool is available: + * https://github.com/JDGrimes/wp-deprecated-code-scanner + * + * @var array + */ + private $deprecated_functions = array( + + // WP 0.71. + 'the_category_head' => array( + 'alt' => 'get_the_category_by_ID()', + 'version' => '0.71', + ), + 'the_category_ID' => array( + 'alt' => 'get_the_category()', + 'version' => '0.71', + ), + + // WP 1.2.0. + 'permalink_link' => array( + 'alt' => 'the_permalink()', + 'version' => '1.2.0', + ), + + // WP 1.5.0. + 'start_wp' => array( + // Verified correct alternative. + 'alt' => 'the Loop', + 'version' => '1.5.0', + ), + + // WP 1.5.1. + 'get_postdata' => array( + 'alt' => 'get_post()', + 'version' => '1.5.1', + ), + + // WP 2.0.0. + 'create_user' => array( + 'alt' => 'wp_create_user()', + 'version' => '2.0.0', + ), + 'next_post' => array( + 'alt' => 'next_post_link()', + 'version' => '2.0.0', + ), + 'previous_post' => array( + 'alt' => 'previous_post_link()', + 'version' => '2.0.0', + ), + 'user_can_create_draft' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_create_post' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_delete_post' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_delete_post_comments' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_post' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_post_comments' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_post_date' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_edit_user' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + 'user_can_set_post_date' => array( + 'alt' => 'current_user_can()', + 'version' => '2.0.0', + ), + + // WP 2.1.0. + 'dropdown_cats' => array( + 'alt' => 'wp_dropdown_categories()', + 'version' => '2.1.0', + ), + 'get_archives' => array( + 'alt' => 'wp_get_archives()', + 'version' => '2.1.0', + ), + 'get_author_link' => array( + 'alt' => 'get_author_posts_url()', + 'version' => '2.1.0', + ), + 'get_autotoggle' => array( + 'alt' => '', + 'version' => '2.1.0', + ), + 'get_link' => array( + 'alt' => 'get_bookmark()', + 'version' => '2.1.0', + ), + 'get_linkcatname' => array( + 'alt' => 'get_category()', + 'version' => '2.1.0', + ), + 'get_linkobjects' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linkobjectsbyname' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linkrating' => array( + 'alt' => 'sanitize_bookmark_field()', + 'version' => '2.1.0', + ), + 'get_links' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_links_list' => array( + 'alt' => 'wp_list_bookmarks()', + 'version' => '2.1.0', + ), + 'get_links_withrating' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linksbyname' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_linksbyname_withrating' => array( + 'alt' => 'get_bookmarks()', + 'version' => '2.1.0', + ), + 'get_settings' => array( + 'alt' => 'get_option()', + 'version' => '2.1.0', + ), + 'link_pages' => array( + 'alt' => 'wp_link_pages()', + 'version' => '2.1.0', + ), + 'links_popup_script' => array( + 'alt' => '', + 'version' => '2.1.0', + ), + 'list_authors' => array( + 'alt' => 'wp_list_authors()', + 'version' => '2.1.0', + ), + 'list_cats' => array( + 'alt' => 'wp_list_categories()', + 'version' => '2.1.0', + ), + 'tinymce_include' => array( + 'alt' => 'wp_editor()', + 'version' => '2.1.0', + ), + 'wp_get_links' => array( + 'alt' => 'wp_list_bookmarks()', + 'version' => '2.1.0', + ), + 'wp_get_linksbyname' => array( + 'alt' => 'wp_list_bookmarks()', + 'version' => '2.1.0', + ), + 'wp_get_post_cats' => array( + 'alt' => 'wp_get_post_categories()', + 'version' => '2.1.0', + ), + 'wp_list_cats' => array( + 'alt' => 'wp_list_categories()', + 'version' => '2.1.0', + ), + 'wp_set_post_cats' => array( + 'alt' => 'wp_set_post_categories()', + 'version' => '2.1.0', + ), + + // WP 2.2.0. + 'comments_rss' => array( + 'alt' => 'get_post_comments_feed_link()', + 'version' => '2.2.0', + ), + + // WP 2.3.0. + 'permalink_single_rss' => array( + 'alt' => 'the_permalink_rss()', + 'version' => '2.3.0', + ), + + // WP 2.5.0. + 'comments_rss_link' => array( + 'alt' => 'post_comments_feed_link()', + 'version' => '2.5.0', + ), + 'documentation_link' => array( + 'alt' => '', + 'version' => '2.5.0', + ), + 'get_attachment_icon' => array( + 'alt' => 'wp_get_attachment_image()', + 'version' => '2.5.0', + ), + 'get_attachment_icon_src' => array( + 'alt' => 'wp_get_attachment_image_src()', + 'version' => '2.5.0', + ), + 'get_attachment_innerHTML' => array( + 'alt' => 'wp_get_attachment_image()', + 'version' => '2.5.0', + ), + 'get_author_rss_link' => array( + 'alt' => 'get_author_feed_link()', + 'version' => '2.5.0', + ), + 'get_category_rss_link' => array( + 'alt' => 'get_category_feed_link()', + 'version' => '2.5.0', + ), + 'get_the_attachment_link' => array( + 'alt' => 'wp_get_attachment_link()', + 'version' => '2.5.0', + ), + 'gzip_compression' => array( + 'alt' => '', + 'version' => '2.5.0', + ), + 'wp_clearcookie' => array( + 'alt' => 'wp_clear_auth_cookie()', + 'version' => '2.5.0', + ), + 'wp_get_cookie_login' => array( + 'alt' => '', + 'version' => '2.5.0', + ), + 'wp_login' => array( + 'alt' => 'wp_signon()', + 'version' => '2.5.0', + ), + 'wp_setcookie' => array( + 'alt' => 'wp_set_auth_cookie()', + 'version' => '2.5.0', + ), + + // WP 2.6.0. + 'dropdown_categories' => array( + 'alt' => 'wp_category_checklist()', + 'version' => '2.6.0', + ), + 'dropdown_link_categories' => array( + 'alt' => 'wp_link_category_checklist()', + 'version' => '2.6.0', + ), + + // WP 2.7.0. + 'get_commentdata' => array( + 'alt' => 'get_comment()', + 'version' => '2.7.0', + ), + // This is a method i.e. WP_Filesystem_Base::find_base_dir() See #731. + 'find_base_dir' => array( + 'alt' => 'WP_Filesystem::abspath()', + 'version' => '2.7.0', + ), + // This is a method i.e. WP_Filesystem_Base::get_base_dir() See #731. + 'get_base_dir' => array( + 'alt' => 'WP_Filesystem::abspath()', + 'version' => '2.7.0', + ), + + // WP 2.8.0. + '__ngettext' => array( + 'alt' => '_n()', + 'version' => '2.8.0', + ), + '__ngettext_noop' => array( + 'alt' => '_n_noop()', + 'version' => '2.8.0', + ), + 'attribute_escape' => array( + 'alt' => 'esc_attr()', + 'version' => '2.8.0', + ), + 'get_author_name' => array( + 'alt' => 'get_the_author_meta(\'display_name\')', + 'version' => '2.8.0', + ), + 'get_category_children' => array( + 'alt' => 'get_term_children()', + 'version' => '2.8.0', + ), + 'get_catname' => array( + 'alt' => 'get_cat_name()', + 'version' => '2.8.0', + ), + 'get_the_author_aim' => array( + 'alt' => 'get_the_author_meta(\'aim\')', + 'version' => '2.8.0', + ), + 'get_the_author_description' => array( + 'alt' => 'get_the_author_meta(\'description\')', + 'version' => '2.8.0', + ), + 'get_the_author_email' => array( + 'alt' => 'get_the_author_meta(\'email\')', + 'version' => '2.8.0', + ), + 'get_the_author_firstname' => array( + 'alt' => 'get_the_author_meta(\'first_name\')', + 'version' => '2.8.0', + ), + 'get_the_author_icq' => array( + 'alt' => 'get_the_author_meta(\'icq\')', + 'version' => '2.8.0', + ), + 'get_the_author_ID' => array( + 'alt' => 'get_the_author_meta(\'ID\')', + 'version' => '2.8.0', + ), + 'get_the_author_lastname' => array( + 'alt' => 'get_the_author_meta(\'last_name\')', + 'version' => '2.8.0', + ), + 'get_the_author_login' => array( + 'alt' => 'get_the_author_meta(\'login\')', + 'version' => '2.8.0', + ), + 'get_the_author_msn' => array( + 'alt' => 'get_the_author_meta(\'msn\')', + 'version' => '2.8.0', + ), + 'get_the_author_nickname' => array( + 'alt' => 'get_the_author_meta(\'nickname\')', + 'version' => '2.8.0', + ), + 'get_the_author_url' => array( + 'alt' => 'get_the_author_meta(\'url\')', + 'version' => '2.8.0', + ), + 'get_the_author_yim' => array( + 'alt' => 'get_the_author_meta(\'yim\')', + 'version' => '2.8.0', + ), + 'js_escape' => array( + 'alt' => 'esc_js()', + 'version' => '2.8.0', + ), + 'register_sidebar_widget' => array( + 'alt' => 'wp_register_sidebar_widget()', + 'version' => '2.8.0', + ), + 'register_widget_control' => array( + 'alt' => 'wp_register_widget_control()', + 'version' => '2.8.0', + ), + 'sanitize_url' => array( + 'alt' => 'esc_url_raw()', + 'version' => '2.8.0', + ), + 'the_author_aim' => array( + 'alt' => 'the_author_meta(\'aim\')', + 'version' => '2.8.0', + ), + 'the_author_description' => array( + 'alt' => 'the_author_meta(\'description\')', + 'version' => '2.8.0', + ), + 'the_author_email' => array( + 'alt' => 'the_author_meta(\'email\')', + 'version' => '2.8.0', + ), + 'the_author_firstname' => array( + 'alt' => 'the_author_meta(\'first_name\')', + 'version' => '2.8.0', + ), + 'the_author_icq' => array( + 'alt' => 'the_author_meta(\'icq\')', + 'version' => '2.8.0', + ), + 'the_author_ID' => array( + 'alt' => 'the_author_meta(\'ID\')', + 'version' => '2.8.0', + ), + 'the_author_lastname' => array( + 'alt' => 'the_author_meta(\'last_name\')', + 'version' => '2.8.0', + ), + 'the_author_login' => array( + 'alt' => 'the_author_meta(\'login\')', + 'version' => '2.8.0', + ), + 'the_author_msn' => array( + 'alt' => 'the_author_meta(\'msn\')', + 'version' => '2.8.0', + ), + 'the_author_nickname' => array( + 'alt' => 'the_author_meta(\'nickname\')', + 'version' => '2.8.0', + ), + 'the_author_url' => array( + 'alt' => 'the_author_meta(\'url\')', + 'version' => '2.8.0', + ), + 'the_author_yim' => array( + 'alt' => 'the_author_meta(\'yim\')', + 'version' => '2.8.0', + ), + 'unregister_sidebar_widget' => array( + 'alt' => 'wp_unregister_sidebar_widget()', + 'version' => '2.8.0', + ), + 'unregister_widget_control' => array( + 'alt' => 'wp_unregister_widget_control()', + 'version' => '2.8.0', + ), + 'wp_specialchars' => array( + 'alt' => 'esc_html()', + 'version' => '2.8.0', + ), + + // WP 2.9.0. + '_c' => array( + 'alt' => '_x()', + 'version' => '2.9.0', + ), + '_nc' => array( + 'alt' => '_nx()', + 'version' => '2.9.0', + ), + 'get_real_file_to_edit' => array( + 'alt' => '', + 'version' => '2.9.0', + ), + 'make_url_footnote' => array( + 'alt' => '', + 'version' => '2.9.0', + ), + 'the_content_rss' => array( + 'alt' => 'the_content_feed()', + 'version' => '2.9.0', + ), + 'translate_with_context' => array( + 'alt' => '_x()', + 'version' => '2.9.0', + ), + + // WP 3.0.0. + 'activate_sitewide_plugin' => array( + 'alt' => 'activate_plugin()', + 'version' => '3.0.0', + ), + 'add_option_update_handler' => array( + 'alt' => 'register_setting()', + 'version' => '3.0.0', + ), + 'automatic_feed_links' => array( + 'alt' => 'add_theme_support( \'automatic-feed-links\' )', + 'version' => '3.0.0', + ), + 'clean_url' => array( + 'alt' => 'esc_url()', + 'version' => '3.0.0', + ), + 'clear_global_post_cache' => array( + 'alt' => 'clean_post_cache()', + 'version' => '3.0.0', + ), + 'codepress_footer_js' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'codepress_get_lang' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'deactivate_sitewide_plugin' => array( + 'alt' => 'deactivate_plugin()', + 'version' => '3.0.0', + ), + 'delete_usermeta' => array( + 'alt' => 'delete_user_meta()', + 'version' => '3.0.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'funky_javascript_callback' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'funky_javascript_fix' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'generate_random_password' => array( + 'alt' => 'wp_generate_password()', + 'version' => '3.0.0', + ), + 'get_alloptions' => array( + 'alt' => 'wp_load_alloptions()', + 'version' => '3.0.0', + ), + 'get_blog_list' => array( + 'alt' => 'wp_get_sites()', + 'version' => '3.0.0', + ), + 'get_most_active_blogs' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'get_profile' => array( + 'alt' => 'get_the_author_meta()', + 'version' => '3.0.0', + ), + 'get_user_details' => array( + 'alt' => 'get_user_by()', + 'version' => '3.0.0', + ), + 'get_usermeta' => array( + 'alt' => 'get_user_meta()', + 'version' => '3.0.0', + ), + 'get_usernumposts' => array( + 'alt' => 'count_user_posts()', + 'version' => '3.0.0', + ), + 'graceful_fail' => array( + 'alt' => 'wp_die()', + 'version' => '3.0.0', + ), + // Verified version & alternative. + 'install_blog_defaults' => array( + 'alt' => 'wp_install_defaults', + 'version' => '3.0.0', + ), + 'is_main_blog' => array( + 'alt' => 'is_main_site()', + 'version' => '3.0.0', + ), + 'is_site_admin' => array( + 'alt' => 'is_super_admin()', + 'version' => '3.0.0', + ), + 'is_taxonomy' => array( + 'alt' => 'taxonomy_exists()', + 'version' => '3.0.0', + ), + 'is_term' => array( + 'alt' => 'term_exists()', + 'version' => '3.0.0', + ), + 'is_wpmu_sitewide_plugin' => array( + 'alt' => 'is_network_only_plugin()', + 'version' => '3.0.0', + ), + 'mu_options' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'remove_option_update_handler' => array( + 'alt' => 'unregister_setting()', + 'version' => '3.0.0', + ), + 'set_current_user' => array( + 'alt' => 'wp_set_current_user()', + 'version' => '3.0.0', + ), + 'update_usermeta' => array( + 'alt' => 'update_user_meta()', + 'version' => '3.0.0', + ), + 'use_codepress' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + 'validate_email' => array( + 'alt' => 'is_email()', + 'version' => '3.0.0', + ), + 'wp_dropdown_cats' => array( + 'alt' => 'wp_dropdown_categories()', + 'version' => '3.0.0', + ), + 'wp_shrink_dimensions' => array( + 'alt' => 'wp_constrain_dimensions()', + 'version' => '3.0.0', + ), + 'wpmu_checkAvailableSpace' => array( + 'alt' => 'is_upload_space_available()', + 'version' => '3.0.0', + ), + 'wpmu_menu' => array( + 'alt' => '', + 'version' => '3.0.0', + ), + + // WP 3.1.0. + 'get_author_user_ids' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_dashboard_blog' => array( + 'alt' => 'get_site()', + 'version' => '3.1.0', + ), + 'get_editable_authors' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_editable_user_ids' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_nonauthor_user_ids' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'get_others_drafts' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + 'get_others_pending' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + 'get_others_unpublished_posts' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + 'get_users_of_blog' => array( + 'alt' => 'get_users()', + 'version' => '3.1.0', + ), + 'install_themes_feature_list' => array( + 'alt' => 'get_theme_feature_list()', + 'version' => '3.1.0', + ), + 'is_plugin_page' => array( + // Verified correct alternative. + 'alt' => 'global $plugin_page and/or get_plugin_page_hookname() hooks', + 'version' => '3.1.0', + ), + 'update_category_cache' => array( + 'alt' => '', + 'version' => '3.1.0', + ), + + // WP 3.2.0. + 'favorite_actions' => array( + 'alt' => 'WP_Admin_Bar', + 'version' => '3.2.0', + ), + 'wp_dashboard_quick_press_output' => array( + 'alt' => 'wp_dashboard_quick_press()', + 'version' => '3.2.0', + ), + 'wp_timezone_supported' => array( + 'alt' => '', + 'version' => '3.2.0', + ), + + // WP 3.3.0. + 'add_contextual_help' => array( + 'alt' => 'get_current_screen()->add_help_tab()', + 'version' => '3.3.0', + ), + 'get_boundary_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_index_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_parent_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_user_by_email' => array( + 'alt' => 'get_user_by(\'email\')', + 'version' => '3.3.0', + ), + 'get_user_metavalues' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'get_userdatabylogin' => array( + 'alt' => 'get_user_by(\'login\')', + 'version' => '3.3.0', + ), + 'index_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'is_blog_user' => array( + 'alt' => 'is_user_member_of_blog()', + 'version' => '3.3.0', + ), + 'media_upload_audio' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'media_upload_file' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'media_upload_image' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'media_upload_video' => array( + 'alt' => 'wp_media_upload_handler()', + 'version' => '3.3.0', + ), + 'parent_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'sanitize_user_object' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'screen_layout' => array( + 'alt' => '$current_screen->render_screen_layout()', + 'version' => '3.3.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'screen_meta' => array( + 'alt' => '$current_screen->render_screen_meta()', + 'version' => '3.3.0', + ), + 'screen_options' => array( + 'alt' => '$current_screen->render_per_page_options()', + 'version' => '3.3.0', + ), + 'start_post_rel_link' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'the_editor' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'type_url_form_audio' => array( + 'alt' => 'wp_media_insert_url_form(\'audio\')', + 'version' => '3.3.0', + ), + 'type_url_form_file' => array( + 'alt' => 'wp_media_insert_url_form(\'file\')', + 'version' => '3.3.0', + ), + 'type_url_form_image' => array( + 'alt' => 'wp_media_insert_url_form(\'image\')', + 'version' => '3.3.0', + ), + 'type_url_form_video' => array( + 'alt' => 'wp_media_insert_url_form(\'video\')', + 'version' => '3.3.0', + ), + 'wp_admin_bar_dashboard_view_site_menu' => array( + 'alt' => '', + 'version' => '3.3.0', + ), + 'wp_preload_dialogs' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wp_print_editor_js' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wp_quicktags' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wp_tiny_mce' => array( + 'alt' => 'wp_editor()', + 'version' => '3.3.0', + ), + 'wpmu_admin_do_redirect' => array( + 'alt' => 'wp_redirect()', + 'version' => '3.3.0', + ), + 'wpmu_admin_redirect_add_updated_param' => array( + 'alt' => 'add_query_arg()', + 'version' => '3.3.0', + ), + + // WP 3.4.0. + 'add_custom_background' => array( + 'alt' => 'add_theme_support( \'custom-background\', $args )', + 'version' => '3.4.0', + ), + 'add_custom_image_header' => array( + 'alt' => 'add_theme_support( \'custom-header\', $args )', + 'version' => '3.4.0', + ), + 'clean_page_cache' => array( + 'alt' => 'clean_post_cache()', + 'version' => '3.4.0', + ), + 'clean_pre' => array( + 'alt' => '', + 'version' => '3.4.0', + ), + 'current_theme_info' => array( + 'alt' => 'wp_get_theme()', + 'version' => '3.4.0', + ), + 'debug_fclose' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'debug_fopen' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'debug_fwrite' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'display_theme' => array( + 'alt' => '', + 'version' => '3.4.0', + ), + 'get_allowed_themes' => array( + 'alt' => 'wp_get_themes( array( \'allowed\' => true ) )', + 'version' => '3.4.0', + ), + 'get_broken_themes' => array( + 'alt' => 'wp_get_themes( array( \'errors\' => true )', + 'version' => '3.4.0', + ), + 'get_current_theme' => array( + 'alt' => 'wp_get_theme()', + 'version' => '3.4.0', + ), + 'get_site_allowed_themes' => array( + 'alt' => 'WP_Theme::get_allowed_on_network()', + 'version' => '3.4.0', + ), + 'get_theme' => array( + 'alt' => 'wp_get_theme( $stylesheet )', + 'version' => '3.4.0', + ), + 'get_theme_data' => array( + 'alt' => 'wp_get_theme()', + 'version' => '3.4.0', + ), + 'get_themes' => array( + 'alt' => 'wp_get_themes()', + 'version' => '3.4.0', + ), + 'logIO' => array( + 'alt' => 'error_log()', + 'version' => '3.4.0', + ), + 'remove_custom_background' => array( + 'alt' => 'remove_theme_support( \'custom-background\' )', + 'version' => '3.4.0', + ), + 'remove_custom_image_header' => array( + 'alt' => 'remove_theme_support( \'custom-header\' )', + 'version' => '3.4.0', + ), + 'update_page_cache' => array( + 'alt' => 'update_post_cache()', + 'version' => '3.4.0', + ), + 'wpmu_get_blog_allowedthemes' => array( + 'alt' => 'WP_Theme::get_allowed_on_site()', + 'version' => '3.4.0', + ), + + // WP 3.4.1. + 'wp_explain_nonce' => array( + 'alt' => 'wp_nonce_ays()', + 'version' => '3.4.1', + ), + + // WP 3.5.0. + '_flip_image_resource' => array( + 'alt' => 'WP_Image_Editor::flip()', + 'version' => '3.5.0', + ), + '_get_post_ancestors' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + '_insert_into_post_button' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + '_media_button' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + '_rotate_image_resource' => array( + 'alt' => 'WP_Image_Editor::rotate()', + 'version' => '3.5.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + '_save_post_hook' => array( + 'alt' => '', + 'version' => '3.5.0', + ), + 'gd_edit_image_support' => array( + 'alt' => 'wp_image_editor_supports()', + 'version' => '3.5.0', + ), + 'get_default_page_to_edit' => array( + 'alt' => 'get_default_post_to_edit( \'page\' )', + 'version' => '3.5.0', + ), + 'get_post_to_edit' => array( + 'alt' => 'get_post()', + 'version' => '3.5.0', + ), + 'get_udims' => array( + 'alt' => 'wp_constrain_dimensions()', + 'version' => '3.5.0', + ), + 'image_resize' => array( + 'alt' => 'wp_get_image_editor()', + 'version' => '3.5.0', + ), + 'sticky_class' => array( + 'alt' => 'post_class()', + 'version' => '3.5.0', + ), + 'user_pass_ok' => array( + 'alt' => 'wp_authenticate()', + 'version' => '3.5.0', + ), + 'wp_cache_reset' => array( + 'alt' => 'WP_Object_Cache::reset()', + 'version' => '3.5.0', + ), + 'wp_create_thumbnail' => array( + 'alt' => 'image_resize()', + 'version' => '3.5.0', + ), + 'wp_get_single_post' => array( + 'alt' => 'get_post()', + 'version' => '3.5.0', + ), + 'wp_load_image' => array( + 'alt' => 'wp_get_image_editor()', + 'version' => '3.5.0', + ), + + // WP 3.6.0. + 'get_user_id_from_string' => array( + 'alt' => 'get_user_by()', + 'version' => '3.6.0', + ), + 'wp_convert_bytes_to_hr' => array( + 'alt' => 'size_format()', + 'version' => '3.6.0', + ), + 'wp_nav_menu_locations_meta_box' => array( + 'alt' => '', + 'version' => '3.6.0', + ), + + // WP 3.7.0. + '_search_terms_tidy' => array( + 'alt' => '', + 'version' => '3.7.0', + ), + 'get_blogaddress_by_domain' => array( + 'alt' => '', + 'version' => '3.7.0', + ), + 'the_attachment_links' => array( + 'alt' => '', + 'version' => '3.7.0', + ), + 'wp_update_core' => array( + 'alt' => 'new Core_Upgrader();', + 'version' => '3.7.0', + ), + 'wp_update_plugin' => array( + 'alt' => 'new Plugin_Upgrader();', + 'version' => '3.7.0', + ), + 'wp_update_theme' => array( + 'alt' => 'new Theme_Upgrader();', + 'version' => '3.7.0', + ), + + // WP 3.8.0. + 'get_screen_icon' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + 'screen_icon' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_incoming_links' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_incoming_links_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_incoming_links_output' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_plugins' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_primary_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_recent_comments_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_secondary' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_secondary_control' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_dashboard_secondary_output' => array( + 'alt' => '', + 'version' => '3.8.0', + ), + + // WP 3.9.0. + '_relocate_children' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'default_topic_count_text' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + 'format_to_post' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + 'get_current_site_name' => array( + 'alt' => 'get_current_site()', + 'version' => '3.9.0', + ), + 'rich_edit_exists' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + 'wpmu_current_site' => array( + 'alt' => '', + 'version' => '3.9.0', + ), + + // WP 4.0.0. + 'get_all_category_ids' => array( + 'alt' => 'get_terms()', + 'version' => '4.0.0', + ), + 'like_escape' => array( + 'alt' => 'wpdb::esc_like()', + 'version' => '4.0.0', + ), + 'url_is_accessable_via_ssl' => array( + 'alt' => '', + 'version' => '4.0.0', + ), + + // WP 4.1.0. + // This is a method from the WP_Customize_Image_Control class. See #731. + 'add_tab' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + // This is a method from the WP_Customize_Image_Control class. See #731. + 'prepare_control' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + // This is a method from the WP_Customize_Image_Control class. See #731. + 'print_tab_image' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + // This is a method from the WP_Customize_Image_Control class. See #731. + 'remove_tab' => array( + 'alt' => '', + 'version' => '4.1.0', + ), + + // WP 4.2.0. + // This is a method from the WP_Customize_Widgets class. See #731. + 'prepreview_added_sidebars_widgets' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + // This is a method from the WP_Customize_Widgets class. See #731. + 'prepreview_added_widget_instance' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + // This is a method from the WP_Customize_Widgets class. See #731. + 'remove_prepreview_filters' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + // This is a method from the WP_Customize_Widgets class. See #731. + 'setup_widget_addition_previews' => array( + 'alt' => 'the \'customize_dynamic_setting_args\' filter', + 'version' => '4.2.0', + ), + + // WP 4.3.0. + '_preview_theme_stylesheet_filter' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + '_preview_theme_template_filter' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'preview_theme' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'preview_theme_ob_filter' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'preview_theme_ob_filter_callback' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + // Verified; see https://core.trac.wordpress.org/ticket/41121, patch 3. + 'wp_ajax_wp_fullscreen_save_post' => array( + 'alt' => '', + 'version' => '4.3.0', + ), + 'wp_htmledit_pre' => array( + 'alt' => 'format_for_editor()', + 'version' => '4.3.0', + ), + 'wp_richedit_pre' => array( + 'alt' => 'format_for_editor()', + 'version' => '4.3.0', + ), + + // WP 4.4.0. + 'create_empty_blog' => array( + 'alt' => '', + 'version' => '4.4.0', + ), + 'force_ssl_login' => array( + 'alt' => 'force_ssl_admin()', + 'version' => '4.4.0', + ), + 'get_admin_users_for_domain' => array( + 'alt' => '', + 'version' => '4.4.0', + ), + 'post_permalink' => array( + 'alt' => 'get_permalink()', + 'version' => '4.4.0', + ), + 'wp_get_http' => array( + 'alt' => 'the WP_Http class', + 'version' => '4.4.0', + ), + // This is a method i.e. WP_Widget_Recent_Comments::flush_widget_cache() See #731. + 'flush_widget_cache' => array( + 'alt' => '', + 'version' => '4.4.0', + ), + + // WP 4.5.0. + 'add_object_page' => array( + 'alt' => 'add_menu_page()', + 'version' => '4.5.0', + ), + 'add_utility_page' => array( + 'alt' => 'add_menu_page()', + 'version' => '4.5.0', + ), + 'comments_popup_script' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + 'get_comments_popup_template' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + 'get_currentuserinfo' => array( + 'alt' => 'wp_get_current_user()', + 'version' => '4.5.0', + ), + 'is_comments_popup' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + 'popuplinks' => array( + 'alt' => '', + 'version' => '4.5.0', + ), + + // WP 4.6.0. + 'post_form_autocomplete_off' => array( + 'alt' => '', + 'version' => '4.6.0', + ), + 'wp_embed_handler_googlevideo' => array( + 'alt' => '', + 'version' => '4.6.0', + ), + 'wp_get_sites' => array( + 'alt' => 'get_sites()', + 'version' => '4.6.0', + ), + + // WP 4.7.0. + '_sort_nav_menu_items' => array( + 'alt' => 'wp_list_sort()', + 'version' => '4.7.0', + ), + '_usort_terms_by_ID' => array( + 'alt' => 'wp_list_sort()', + 'version' => '4.7.0', + ), + '_usort_terms_by_name' => array( + 'alt' => 'wp_list_sort()', + 'version' => '4.7.0', + ), + 'get_paged_template' => array( + 'alt' => '', + 'version' => '4.7.0', + ), + 'wp_get_network' => array( + 'alt' => 'get_network()', + 'version' => '4.7.0', + ), + 'wp_kses_js_entities' => array( + 'alt' => '', + 'version' => '4.7.0', + ), + + // WP 4.8.0. + 'wp_dashboard_plugins_output' => array( + 'alt' => '', + 'version' => '4.8.0', + ), + + // WP 4.9.0. + 'get_shortcut_link' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + 'is_user_option_local' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + 'wp_ajax_press_this_add_category' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + 'wp_ajax_press_this_save_post' => array( + 'alt' => '', + 'version' => '4.9.0', + ), + + // WP 5.1.0. + 'insert_blog' => array( + 'alt' => 'wp_insert_site()', + 'version' => '5.1.0', + ), + 'install_blog' => array( + 'alt' => '', + 'version' => '5.1.0', + ), + + // WP 5.3.0. + '_wp_json_prepare_data' => array( + 'alt' => '', + 'version' => '5.3.0', + ), + '_wp_privacy_requests_screen_options' => array( + 'alt' => '', + 'version' => '5.3.0', + ), + 'update_user_status' => array( + 'alt' => 'wp_update_user()', + 'version' => '5.3.0', + ), + + // WP 5.4.0. + 'wp_get_user_request_data' => array( + 'alt' => 'wp_get_user_request()', + 'version' => '5.4.0', + ), + ); + + /** + * Groups of functions to restrict. + * + * @return array + */ + public function getGroups() { + // Make sure all array keys are lowercase. + $this->deprecated_functions = array_change_key_case( $this->deprecated_functions, CASE_LOWER ); + + return array( + 'deprecated_functions' => array( + 'functions' => array_keys( $this->deprecated_functions ), + ), + ); + } + + /** + * Process a matched token. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. Will + * always be 'deprecated_functions'. + * @param string $matched_content The token content (function name) which was matched. + * + * @return void + */ + public function process_matched_token( $stackPtr, $group_name, $matched_content ) { + + $this->get_wp_version_from_cl(); + + $function_name = strtolower( $matched_content ); + + $message = '%s() has been deprecated since WordPress version %s.'; + $data = array( + $matched_content, + $this->deprecated_functions[ $function_name ]['version'], + ); + + if ( ! empty( $this->deprecated_functions[ $function_name ]['alt'] ) ) { + $message .= ' Use %s instead.'; + $data[] = $this->deprecated_functions[ $function_name ]['alt']; + } + + $this->addMessage( + $message, + $stackPtr, + ( version_compare( $this->deprecated_functions[ $function_name ]['version'], $this->minimum_supported_version, '<' ) ), + $this->string_to_errorcode( $matched_content . 'Found' ), + $data + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php new file mode 100644 index 000000000..0758def26 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParameterValuesSniff.php @@ -0,0 +1,216 @@ + array( + * (int) Target parameter position, 1-based. => array( + * (string) Parameter value. => array( + * 'alt' => (string) Suggested alternative. + * 'version' => (int) The WordPress version when deprecated. + * ) + * ) + * ) + * ); + */ + protected $target_functions = array( + 'add_settings_field' => array( + 4 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + 'add_settings_section' => array( + 4 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + 'bloginfo' => array( + 1 => array( + 'home' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'siteurl' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'text_direction' => array( + 'alt' => 'is_rtl()', + 'version' => '2.2.0', + ), + ), + ), + 'get_bloginfo' => array( + 1 => array( + 'home' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'siteurl' => array( + 'alt' => 'the "url" argument', + 'version' => '2.2.0', + ), + 'text_direction' => array( + 'alt' => 'is_rtl()', + 'version' => '2.2.0', + ), + ), + ), + 'register_setting' => array( + 1 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + 'unregister_setting' => array( + 1 => array( + 'misc' => array( + 'alt' => 'another settings group', + 'version' => '3.0.0', + ), + 'privacy' => array( + 'alt' => 'another settings group', + 'version' => '3.5.0', + ), + ), + ), + ); + + /** + * Process the parameters of a matched function. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $this->get_wp_version_from_cl(); + $param_count = \count( $parameters ); + foreach ( $this->target_functions[ $matched_content ] as $position => $parameter_args ) { + + // Stop if the position is higher then the total number of parameters. + if ( $position > $param_count ) { + break; + } + + $this->process_parameter( $matched_content, $parameters[ $position ], $parameter_args ); + } + } + + /** + * Process the parameter of a matched function. + * + * @since 1.0.0 + * + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameter Array with start and end token positon of the parameter. + * @param array $parameter_args Array with alternative and WordPress deprecation version of the parameter. + * + * @return void + */ + protected function process_parameter( $matched_content, $parameter, $parameter_args ) { + + $parameter_position = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + $parameter['start'], + $parameter['end'] + 1, + true + ); + + if ( false === $parameter_position ) { + return; + } + + $matched_parameter = $this->strip_quotes( $this->tokens[ $parameter_position ]['content'] ); + if ( ! isset( $parameter_args[ $matched_parameter ] ) ) { + return; + } + + $message = 'The parameter value "%s" has been deprecated since WordPress version %s.'; + $data = array( + $matched_parameter, + $parameter_args[ $matched_parameter ]['version'], + ); + + if ( ! empty( $parameter_args[ $matched_parameter ]['alt'] ) ) { + $message .= ' Use %s instead.'; + $data[] = $parameter_args[ $matched_parameter ]['alt']; + } + + $is_error = version_compare( $parameter_args[ $matched_parameter ]['version'], $this->minimum_supported_version, '<' ); + $this->addMessage( + $message, + $parameter_position, + $is_error, + $this->string_to_errorcode( 'Found' ), + $data + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php new file mode 100644 index 000000000..3d45bafc7 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DeprecatedParametersSniff.php @@ -0,0 +1,338 @@ + value + * in a custom ruleset. + * + * @uses \WordPressCS\WordPress\Sniff::$minimum_supported_version + */ +class DeprecatedParametersSniff extends AbstractFunctionParameterSniff { + + /** + * The group name for this group of functions. + * + * @since 0.12.0 + * + * @var string + */ + protected $group_name = 'wp_deprecated_parameters'; + + /** + * Array of function, argument, and default value for deprecated argument. + * + * The functions are ordered alphabetically. + * Last updated for WordPress 4.8.0. + * + * @since 0.12.0 + * + * @var array Multidimensional array with parameter details. + * $target_functions = array( + * (string) Function name. => array( + * (int) Target parameter position, 1-based. => array( + * 'value' => (mixed) Expected default value for the + * deprecated parameter. Currently the default + * values: true, false, null, empty arrays and + * both empty and non-empty strings can be + * handled correctly by the process_parameters() + * method. When an additional default value is + * added, the relevant code in the + * process_parameters() method will need to be + * adjusted. + * 'version' => (int) The WordPress version when deprecated. + * ) + * ) + * ); + */ + protected $target_functions = array( + + 'add_option' => array( + 3 => array( + 'value' => '', + 'version' => '2.3.0', + ), + ), + 'comments_link' => array( + 1 => array( + 'value' => '', + 'version' => '0.72', + ), + 2 => array( + 'value' => '', + 'version' => '1.3.0', + ), + ), + 'comments_number' => array( + 4 => array( + 'value' => '', + 'version' => '1.3.0', + ), + ), + 'convert_chars' => array( + 2 => array( + 'value' => '', + 'version' => '0.71', + ), + ), + 'discover_pingback_server_uri' => array( + 2 => array( + 'value' => '', + 'version' => '2.7.0', + ), + ), + 'get_category_parents' => array( + 5 => array( + 'value' => array(), + 'version' => '4.8.0', + ), + ), + 'get_delete_post_link' => array( + 2 => array( + 'value' => '', + 'version' => '3.0.0', + ), + ), + 'get_last_updated' => array( + 1 => array( + 'value' => '', + 'version' => '3.0.0', // Was previously part of MU. + ), + ), + 'get_the_author' => array( + 1 => array( + 'value' => '', + 'version' => '2.1.0', + ), + ), + 'get_user_option' => array( + 3 => array( + 'value' => '', + 'version' => '2.3.0', + ), + ), + 'get_wp_title_rss' => array( + 1 => array( + 'value' => '–', + 'version' => '4.4.0', + ), + ), + 'is_email' => array( + 2 => array( + 'value' => false, + 'version' => '3.0.0', + ), + ), + 'load_plugin_textdomain' => array( + 2 => array( + 'value' => false, + 'version' => '2.7.0', + ), + ), + 'safecss_filter_attr' => array( + 2 => array( + 'value' => '', + 'version' => '2.8.1', + ), + ), + 'the_attachment_link' => array( + 3 => array( + 'value' => false, + 'version' => '2.5.0', + ), + ), + 'the_author' => array( + 1 => array( + 'value' => '', + 'version' => '2.1.0', + ), + 2 => array( + 'value' => true, + 'version' => '1.5.0', + ), + ), + 'the_author_posts_link' => array( + 1 => array( + 'value' => '', + 'version' => '2.1.0', + ), + ), + 'trackback_rdf' => array( + 1 => array( + 'value' => '', + 'version' => '2.5.0', + ), + ), + 'trackback_url' => array( + 1 => array( + 'value' => true, + 'version' => '2.5.0', + ), + ), + 'update_blog_option' => array( + 4 => array( + 'value' => null, + 'version' => '3.1.0', + ), + ), + 'update_blog_status' => array( + 4 => array( + 'value' => null, + 'version' => '3.1.0', + ), + ), + 'update_user_status' => array( + 4 => array( + 'value' => null, + 'version' => '3.0.2', + ), + ), + 'unregister_setting' => array( + 4 => array( + 'value' => '', + 'version' => '4.7.0', + ), + ), + 'wp_get_http_headers' => array( + 2 => array( + 'value' => false, + 'version' => '2.7.0', + ), + ), + 'wp_get_sidebars_widgets' => array( + 1 => array( + 'value' => true, + 'version' => '2.8.1', + ), + ), + 'wp_install' => array( + 5 => array( + 'value' => '', + 'version' => '2.6.0', + ), + ), + 'wp_new_user_notification' => array( + 2 => array( + 'value' => null, + 'version' => '4.3.1', + ), + ), + 'wp_notify_postauthor' => array( + 2 => array( + 'value' => null, + 'version' => '3.8.0', + ), + ), + 'wp_title_rss' => array( + 1 => array( + 'value' => '–', + 'version' => '4.4.0', + ), + ), + 'wp_upload_bits' => array( + 2 => array( + 'value' => null, + 'version' => '2.0.0', + ), + ), + 'xfn_check' => array( + 3 => array( + 'value' => '', + 'version' => '2.5.0', + ), + ), + ); + + /** + * Process the parameters of a matched function. + * + * @since 0.12.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + $this->get_wp_version_from_cl(); + + $paramCount = \count( $parameters ); + foreach ( $this->target_functions[ $matched_content ] as $position => $parameter_args ) { + + // Check that number of parameters defined is not less than the position to check. + if ( $position > $paramCount ) { + break; + } + + // The list will need to updated if the default value is not supported. + switch ( $parameters[ $position ]['raw'] ) { + case 'true': + $matched_parameter = true; + break; + case 'false': + $matched_parameter = false; + break; + case 'null': + $matched_parameter = null; + break; + case 'array()': + case '[]': + $matched_parameter = array(); + break; + default: + $matched_parameter = $this->strip_quotes( $parameters[ $position ]['raw'] ); + break; + } + + if ( $parameter_args['value'] === $matched_parameter ) { + continue; + } + + $message = 'The parameter "%s" at position #%s of %s() has been deprecated since WordPress version %s.'; + $is_error = version_compare( $parameter_args['version'], $this->minimum_supported_version, '<' ); + $code = $this->string_to_errorcode( ucfirst( $matched_content ) . 'Param' . $position . 'Found' ); + + $data = array( + $parameters[ $position ]['raw'], + $position, + $matched_content, + $parameter_args['version'], + ); + + if ( isset( $parameter_args['value'] ) && $position < $paramCount ) { + $message .= ' Use "%s" instead.'; + $data[] = (string) $parameter_args['value']; + } else { + $message .= ' Instead do not pass the parameter.'; + } + + $this->addMessage( $message, $stackPtr, $is_error, $code, $data, 0 ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php new file mode 100644 index 000000000..bcd960c44 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedConstantsSniff.php @@ -0,0 +1,217 @@ + 'get_stylesheet_directory()', + 'TEMPLATEPATH' => 'get_template_directory()', + 'PLUGINDIR' => 'WP_PLUGIN_DIR', + 'MUPLUGINDIR' => 'WPMU_PLUGIN_DIR', + 'HEADER_IMAGE' => 'add_theme_support( \'custom-header\' )', + 'NO_HEADER_TEXT' => 'add_theme_support( \'custom-header\' )', + 'HEADER_TEXTCOLOR' => 'add_theme_support( \'custom-header\' )', + 'HEADER_IMAGE_WIDTH' => 'add_theme_support( \'custom-header\' )', + 'HEADER_IMAGE_HEIGHT' => 'add_theme_support( \'custom-header\' )', + 'BACKGROUND_COLOR' => 'add_theme_support( \'custom-background\' )', + 'BACKGROUND_IMAGE' => 'add_theme_support( \'custom-background\' )', + ); + + /** + * Array of functions to check. + * + * @since 0.14.0 + * + * @var array => + */ + protected $target_functions = array( + 'define' => 1, + ); + + /** + * Array of tokens which if found preceding the $stackPtr indicate that a T_STRING is not a constant. + * + * @var array + */ + private $preceding_tokens_to_ignore = array( + \T_NAMESPACE => true, + \T_USE => true, + \T_CLASS => true, + \T_TRAIT => true, + \T_INTERFACE => true, + \T_EXTENDS => true, + \T_IMPLEMENTS => true, + \T_NEW => true, + \T_FUNCTION => true, + \T_DOUBLE_COLON => true, + \T_OBJECT_OPERATOR => true, + \T_INSTANCEOF => true, + \T_GOTO => true, + ); + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + if ( isset( $this->target_functions[ strtolower( $this->tokens[ $stackPtr ]['content'] ) ] ) ) { + // Disallow excluding function groups for this sniff. + $this->exclude = array(); + + return parent::process_token( $stackPtr ); + + } else { + return $this->process_arbitrary_tstring( $stackPtr ); + } + } + + /** + * Process an arbitrary T_STRING token to determine whether it is one of the target constants. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_arbitrary_tstring( $stackPtr ) { + $content = $this->tokens[ $stackPtr ]['content']; + + if ( ! isset( $this->discouraged_constants[ $content ] ) ) { + return; + } + + $next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + if ( false !== $next && \T_OPEN_PARENTHESIS === $this->tokens[ $next ]['code'] ) { + // Function call or declaration. + return; + } + + $prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); + if ( false !== $prev && isset( $this->preceding_tokens_to_ignore[ $this->tokens[ $prev ]['code'] ] ) ) { + // Not the use of a constant. + return; + } + + if ( $this->is_token_namespaced( $stackPtr ) === true ) { + // Namespaced constant of the same name. + return; + } + + if ( false !== $prev + && \T_CONST === $this->tokens[ $prev ]['code'] + && true === $this->is_class_constant( $prev ) + ) { + // Class constant of the same name. + return; + } + + /* + * Deal with a number of variations of use statements. + */ + for ( $i = $stackPtr; $i > 0; $i-- ) { + if ( $this->tokens[ $i ]['line'] !== $this->tokens[ $stackPtr ]['line'] ) { + break; + } + } + + $first_on_line = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $i + 1 ), null, true ); + if ( false !== $first_on_line && \T_USE === $this->tokens[ $first_on_line ]['code'] ) { + $next_on_line = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $first_on_line + 1 ), null, true ); + if ( false !== $next_on_line ) { + if ( ( \T_STRING === $this->tokens[ $next_on_line ]['code'] + && 'const' === $this->tokens[ $next_on_line ]['content'] ) + || \T_CONST === $this->tokens[ $next_on_line ]['code'] // Happens in some PHPCS versions. + ) { + $has_ns_sep = $this->phpcsFile->findNext( \T_NS_SEPARATOR, ( $next_on_line + 1 ), $stackPtr ); + if ( false !== $has_ns_sep ) { + // Namespaced const (group) use statement. + return; + } + } else { + // Not a const use statement. + return; + } + } + } + + // Ok, this is really one of the discouraged constants. + $this->phpcsFile->addWarning( + 'Found usage of constant "%s". Use %s instead.', + $stackPtr, + $this->string_to_errorcode( $content . 'UsageFound' ), + array( + $content, + $this->discouraged_constants[ $content ], + ) + ); + } + + /** + * Process the parameters of a matched `define` function call. + * + * @since 0.14.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $function_name = strtolower( $matched_content ); + $target_param = $this->target_functions[ $function_name ]; + + // Was the target parameter passed ? + if ( ! isset( $parameters[ $target_param ] ) ) { + return; + } + + $raw_content = $this->strip_quotes( $parameters[ $target_param ]['raw'] ); + + if ( isset( $this->discouraged_constants[ $raw_content ] ) ) { + $this->phpcsFile->addWarning( + 'Found declaration of constant "%s". Use %s instead.', + $stackPtr, + $this->string_to_errorcode( $raw_content . 'DeclarationFound' ), + array( + $raw_content, + $this->discouraged_constants[ $raw_content ], + ) + ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php new file mode 100644 index 000000000..d51504a3d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php @@ -0,0 +1,57 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'query_posts' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use WP_Query instead.', + 'functions' => array( + 'query_posts', + ), + ), + + 'wp_reset_query' => array( + 'type' => 'warning', + 'message' => '%s() is discouraged. Use wp_reset_postdata() instead.', + 'functions' => array( + 'wp_reset_query', + ), + ), + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php new file mode 100644 index 000000000..9c1f5f1e9 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourceParametersSniff.php @@ -0,0 +1,223 @@ + => + */ + protected $target_functions = array( + 'wp_register_script' => true, + 'wp_enqueue_script' => true, + 'wp_register_style' => true, + 'wp_enqueue_style' => true, + ); + + /** + * False + the empty tokens array. + * + * This array is enriched with the $emptyTokens array in the register() method. + * + * @var array + */ + private $false_tokens = array( + \T_FALSE => \T_FALSE, + ); + + /** + * Token codes which are "safe" to accept to determine whether a version would evaluate to `false`. + * + * This array is enriched with the several of the PHPCS token arrays in the register() method. + * + * @var array + */ + private $safe_tokens = array( + \T_NULL => \T_NULL, + \T_FALSE => \T_FALSE, + \T_TRUE => \T_TRUE, + \T_LNUMBER => \T_LNUMBER, + \T_DNUMBER => \T_DNUMBER, + \T_CONSTANT_ENCAPSED_STRING => \T_CONSTANT_ENCAPSED_STRING, + \T_START_NOWDOC => \T_START_NOWDOC, + \T_NOWDOC => \T_NOWDOC, + \T_END_NOWDOC => \T_END_NOWDOC, + \T_OPEN_PARENTHESIS => \T_OPEN_PARENTHESIS, + \T_CLOSE_PARENTHESIS => \T_CLOSE_PARENTHESIS, + \T_STRING_CONCAT => \T_STRING_CONCAT, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * Overloads and calls the parent method to allow for adding additional tokens to the $safe_tokens property. + * + * @return array + */ + public function register() { + $this->false_tokens += Tokens::$emptyTokens; + + $this->safe_tokens += Tokens::$emptyTokens; + $this->safe_tokens += Tokens::$assignmentTokens; + $this->safe_tokens += Tokens::$comparisonTokens; + $this->safe_tokens += Tokens::$operators; + $this->safe_tokens += Tokens::$booleanOperators; + $this->safe_tokens += Tokens::$castTokens; + + return parent::register(); + } + + /** + * Process the parameters of a matched function. + * + * @since 1.0.0 + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + + // Check to see if a source ($src) is specified. + if ( ! isset( $parameters[2] ) ) { + return; + } + + /* + * Version Check: Check to make sure the version is set explicitly. + */ + + if ( ! isset( $parameters[4] ) || 'null' === $parameters[4]['raw'] ) { + $type = 'script'; + if ( strpos( $matched_content, '_style' ) !== false ) { + $type = 'style'; + } + + $this->phpcsFile->addError( + 'Resource version not set in call to %s(). This means new versions of the %s will not always be loaded due to browser caching.', + $stackPtr, + 'MissingVersion', + array( $matched_content, $type ) + ); + } else { + // The version argument should have a non-false value. + if ( $this->is_falsy( $parameters[4]['start'], $parameters[4]['end'] ) ) { + $this->phpcsFile->addError( + 'Version parameter is not explicitly set or has been set to an equivalent of "false" for %s; ' . + 'This means that the WordPress core version will be used which is not recommended for plugin or theme development.', + $stackPtr, + 'NoExplicitVersion', + array( $matched_content ) + ); + } + } + + /* + * In footer Check + * + * Check to make sure that $in_footer is set to true. + * It will warn the user to make sure it is intended. + * + * Only wp_register_script and wp_enqueue_script need this check, + * as this parameter is not available to wp_register_style and wp_enqueue_style. + */ + if ( 'wp_register_script' !== $matched_content && 'wp_enqueue_script' !== $matched_content ) { + return; + } + + if ( ! isset( $parameters[5] ) ) { + // If in footer is not set, throw a warning about the default. + $this->phpcsFile->addWarning( + 'In footer ($in_footer) is not set explicitly %s; ' . + 'It is recommended to load scripts in the footer. Please set this value to `true` to load it in the footer, or explicitly `false` if it should be loaded in the header.', + $stackPtr, + 'NotInFooter', + array( $matched_content ) + ); + } + } + + /** + * Determine if a range has a falsy value. + * + * @param int $start The position to start looking from. + * @param int $end The position to stop looking (inclusive). + * + * @return bool True if the parameter is falsy. + * False if the parameter is not falsy or when it + * couldn't be reliably determined. + */ + protected function is_falsy( $start, $end ) { + + // Find anything excluding the false tokens. + $has_non_false = $this->phpcsFile->findNext( $this->false_tokens, $start, ( $end + 1 ), true ); + // If no non-false tokens are found, we are good. + if ( false === $has_non_false ) { + return true; + } + + $code_string = ''; + for ( $i = $start; $i <= $end; $i++ ) { + if ( isset( $this->safe_tokens[ $this->tokens[ $i ]['code'] ] ) === false ) { + // Function call/variable or other token which makes it neigh impossible + // to determine whether the actual value would evaluate to false. + return false; + } + + if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) === true ) { + continue; + } + + $code_string .= $this->tokens[ $i ]['content']; + } + + if ( '' === $code_string ) { + return false; + } + + // Evaluate the argument to figure out the outcome is false or not. + // phpcs:ignore Squiz.PHP.Eval -- No harm here. + return ( false === eval( "return (bool) $code_string;" ) ); + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php new file mode 100644 index 000000000..27572e95d --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php @@ -0,0 +1,64 @@ +tokens[ $stackPtr ]; + + if ( preg_match( '# rel=\\\\?[\'"]?stylesheet\\\\?[\'"]?#', $token['content'] ) > 0 ) { + $this->phpcsFile->addError( + 'Stylesheets must be registered/enqueued via wp_enqueue_style', + $stackPtr, + 'NonEnqueuedStylesheet' + ); + } + + if ( preg_match( '#]*(?<=src=)#', $token['content'] ) > 0 ) { + $this->phpcsFile->addError( + 'Scripts must be registered/enqueued via wp_enqueue_script', + $stackPtr, + 'NonEnqueuedScript' + ); + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php new file mode 100644 index 000000000..37bf68b2a --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/GlobalVariablesOverrideSniff.php @@ -0,0 +1,466 @@ + true, + 'wp_cockneyreplace' => true, + ); + + /** + * Scoped object and function structures to skip over as + * variables will have a different scope within those. + * + * @since 1.1.0 + * + * @var array + */ + private $skip_over = array( + \T_FUNCTION => true, + \T_CLOSURE => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @since 0.3.0 + * @since 1.1.0 Added class tokens for improved test classes skipping. + * + * @return array + */ + public function register() { + // Add the OO scope tokens to the $skip_over property. + $this->skip_over += Tokens::$ooScopeTokens; + + $targets = array( + \T_GLOBAL, + \T_VARIABLE, + \T_LIST, + \T_OPEN_SHORT_ARRAY, + ); + + // Only used to skip over test classes. + $targets += Tokens::$ooScopeTokens; + + return $targets; + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.3.0 + * @since 1.1.0 Split the token specific logic off into separate methods. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_token( $stackPtr ) { + + $token = $this->tokens[ $stackPtr ]; + + // Ignore variable overrides in test classes. + if ( isset( Tokens::$ooScopeTokens[ $token['code'] ] ) ) { + + if ( true === $this->is_test_class( $stackPtr ) + && $token['scope_condition'] === $stackPtr + && isset( $token['scope_closer'] ) + ) { + // Skip forward to end of test class. + return $token['scope_closer']; + } + + // Otherwise ignore the tokens as they were only registered to enable skipping over test classes. + return; + } + + /* + * Examine variables within a function scope based on a `global` statement in the + * function. + * Examine variables not within a function scope, but within a list construct, based + * on that. + * Examine variables not within a function scope and access to the `$GLOBALS` + * variable based on the variable token. + */ + $in_function_scope = $this->phpcsFile->hasCondition( $stackPtr, array( \T_FUNCTION, \T_CLOSURE ) ); + + if ( ( \T_LIST === $token['code'] || \T_OPEN_SHORT_ARRAY === $token['code'] ) + && false === $in_function_scope + && false === $this->treat_files_as_scoped + ) { + return $this->process_list_assignment( $stackPtr ); + } elseif ( \T_VARIABLE === $token['code'] + && ( '$GLOBALS' === $token['content'] + || ( false === $in_function_scope && false === $this->treat_files_as_scoped ) ) + ) { + return $this->process_variable_assignment( $stackPtr ); + } elseif ( \T_GLOBAL === $token['code'] + && ( true === $in_function_scope || true === $this->treat_files_as_scoped ) + ) { + return $this->process_global_statement( $stackPtr, $in_function_scope ); + } + } + + /** + * Check that global variables declared via a list construct are prefixed. + * + * @internal No need to take special measures for nested lists. Nested or not, + * each list part can only contain one variable being written to. + * + * @since 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + protected function process_list_assignment( $stackPtr ) { + $list_open_close = $this->find_list_open_close( $stackPtr ); + if ( false === $list_open_close ) { + // Short array, not short list. + return; + } + + $var_pointers = $this->get_list_variables( $stackPtr, $list_open_close ); + foreach ( $var_pointers as $ptr ) { + $this->process_variable_assignment( $ptr, true ); + } + + // No need to re-examine these variables. + return $list_open_close['closer']; + } + + /** + * Check that defined global variables are prefixed. + * + * @since 1.1.0 Logic was previously contained in the process_token() method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param bool $in_list Whether or not this is a variable in a list assignment. + * Defaults to false. + * + * @return void + */ + protected function process_variable_assignment( $stackPtr, $in_list = false ) { + + if ( $this->has_whitelist_comment( 'override', $stackPtr ) === true ) { + return; + } + + $token = $this->tokens[ $stackPtr ]; + $var_name = substr( $token['content'], 1 ); // Strip the dollar sign. + $data = array(); + + // Determine the variable name for `$GLOBALS['array_key']`. + if ( 'GLOBALS' === $var_name ) { + $bracketPtr = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + if ( false === $bracketPtr || \T_OPEN_SQUARE_BRACKET !== $this->tokens[ $bracketPtr ]['code'] || ! isset( $this->tokens[ $bracketPtr ]['bracket_closer'] ) ) { + return; + } + + // Retrieve the array key and avoid getting tripped up by some simple obfuscation. + $var_name = ''; + $start = ( $bracketPtr + 1 ); + for ( $ptr = $start; $ptr < $this->tokens[ $bracketPtr ]['bracket_closer']; $ptr++ ) { + /* + * If the globals array key contains a variable, constant, function call + * or interpolated variable, bow out. + */ + if ( \T_VARIABLE === $this->tokens[ $ptr ]['code'] + || \T_STRING === $this->tokens[ $ptr ]['code'] + || \T_DOUBLE_QUOTED_STRING === $this->tokens[ $ptr ]['code'] + ) { + return; + } + + if ( \T_CONSTANT_ENCAPSED_STRING === $this->tokens[ $ptr ]['code'] ) { + $var_name .= $this->strip_quotes( $this->tokens[ $ptr ]['content'] ); + } + } + + if ( '' === $var_name ) { + // Shouldn't happen, but just in case. + return; + } + + // Set up the data for the error message. + $data[] = '$GLOBALS[\'' . $var_name . '\']'; + } + + /* + * Is this one of the WP global variables ? + */ + if ( isset( $this->wp_globals[ $var_name ] ) === false ) { + return; + } + + /* + * Is this one of the WP global variables which are allowed to be overwritten ? + */ + if ( isset( $this->override_allowed[ $var_name ] ) === true ) { + return; + } + + /* + * Check if the variable value is being changed. + */ + if ( false === $in_list + && false === $this->is_assignment( $stackPtr ) + && false === $this->is_foreach_as( $stackPtr ) + ) { + return; + } + + /* + * Function parameters with the same name as a WP global variable are fine, + * including when they are being assigned a default value. + */ + if ( false === $in_list && isset( $this->tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + foreach ( $this->tokens[ $stackPtr ]['nested_parenthesis'] as $opener => $closer ) { + if ( isset( $this->tokens[ $opener ]['parenthesis_owner'] ) + && ( \T_FUNCTION === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] + || \T_CLOSURE === $this->tokens[ $this->tokens[ $opener ]['parenthesis_owner'] ]['code'] ) + ) { + return; + } + } + unset( $opener, $closer ); + } + + /* + * Class property declarations with the same name as WP global variables are fine. + */ + if ( false === $in_list && true === $this->is_class_property( $stackPtr ) ) { + return; + } + + // Still here ? In that case, the WP global variable is being tampered with. + $this->add_error( $stackPtr, $data ); + } + + /** + * Check that global variables imported into a function scope using a global statement + * are not being overruled. + * + * @since 1.1.0 Logic was previously contained in the process_token() method. + * + * @param int $stackPtr The position of the current token in the stack. + * @param bool $in_function_scope Whether the global statement is within a scoped function/closure. + * + * @return void + */ + protected function process_global_statement( $stackPtr, $in_function_scope ) { + /* + * Collect the variables to watch for. + */ + $search = array(); + $ptr = ( $stackPtr + 1 ); + while ( isset( $this->tokens[ $ptr ] ) ) { + $var = $this->tokens[ $ptr ]; + + // Halt the loop at end of statement. + if ( \T_SEMICOLON === $var['code'] ) { + break; + } + + if ( \T_VARIABLE === $var['code'] ) { + $var_name = substr( $var['content'], 1 ); + if ( isset( $this->wp_globals[ $var_name ] ) + && isset( $this->override_allowed[ $var_name ] ) === false + ) { + $search[] = $var['content']; + } + } + + $ptr++; + } + unset( $var ); + + if ( empty( $search ) ) { + return; + } + + /* + * Search for assignments to the imported global variables within the relevant scope. + */ + $start = $ptr; + if ( true === $in_function_scope ) { + $function_cond = $this->phpcsFile->getCondition( $stackPtr, \T_FUNCTION ); + $closure_cond = $this->phpcsFile->getCondition( $stackPtr, \T_CLOSURE ); + $scope_cond = max( $function_cond, $closure_cond ); // If false, it will evaluate as zero, so this is fine. + if ( isset( $this->tokens[ $scope_cond ]['scope_closer'] ) === false ) { + // Live coding or parse error. + return; + } + $end = $this->tokens[ $scope_cond ]['scope_closer']; + } else { + // Global statement in the global namespace with file is being treated as scoped. + $end = $this->phpcsFile->numTokens; + } + + for ( $ptr = $start; $ptr < $end; $ptr++ ) { + + // Skip over nested functions, classes and the likes. + if ( isset( $this->skip_over[ $this->tokens[ $ptr ]['code'] ] ) ) { + if ( ! isset( $this->tokens[ $ptr ]['scope_closer'] ) ) { + // Live coding or parse error. + break; + } + + $ptr = $this->tokens[ $ptr ]['scope_closer']; + continue; + } + + // Make sure to recognize assignments to variables in a list construct. + if ( \T_LIST === $this->tokens[ $ptr ]['code'] + || \T_OPEN_SHORT_ARRAY === $this->tokens[ $ptr ]['code'] + ) { + $list_open_close = $this->find_list_open_close( $ptr ); + + if ( false === $list_open_close ) { + // Short array, not short list. + continue; + } + + $var_pointers = $this->get_list_variables( $ptr, $list_open_close ); + foreach ( $var_pointers as $ptr ) { + $var_name = $this->tokens[ $ptr ]['content']; + if ( '$GLOBALS' === $var_name ) { + $var_name = '$' . $this->strip_quotes( $this->get_array_access_key( $ptr ) ); + } + + if ( \in_array( $var_name, $search, true ) ) { + $this->process_variable_assignment( $ptr, true ); + } + } + + // No need to re-examine these variables. + $ptr = $list_open_close['closer']; + continue; + } + + if ( \T_VARIABLE !== $this->tokens[ $ptr ]['code'] ) { + continue; + } + + if ( \in_array( $this->tokens[ $ptr ]['content'], $search, true ) === false ) { + // Not one of the variables we're interested in. + continue; + } + + // Don't throw false positives for static class properties. + if ( $this->is_class_object_call( $ptr ) === true ) { + continue; + } + + if ( true === $this->is_assignment( $ptr ) ) { + $this->maybe_add_error( $ptr ); + continue; + } + + // Check if this is a variable assignment within a `foreach()` declaration. + if ( $this->is_foreach_as( $ptr ) === true ) { + $this->maybe_add_error( $ptr ); + } + } + } + + /** + * Add the error if there is no whitelist comment present. + * + * @since 0.11.0 + * @since 1.1.0 - Visibility changed from public to protected. + * - Check for being in a test class moved to the process_token() method. + * + * @param int $stackPtr The position of the token to throw the error for. + * + * @return void + */ + protected function maybe_add_error( $stackPtr ) { + if ( $this->has_whitelist_comment( 'override', $stackPtr ) === false ) { + $this->add_error( $stackPtr ); + } + } + + /** + * Add the error. + * + * @since 1.1.0 + * + * @param int $stackPtr The position of the token to throw the error for. + * @param array $data Optional. Array containing one entry holding the + * name of the variable being overruled. + * Defaults to the 'content' of the $stackPtr token. + * + * @return void + */ + protected function add_error( $stackPtr, $data = array() ) { + if ( empty( $data ) ) { + $data[] = $this->tokens[ $stackPtr ]['content']; + } + + $this->phpcsFile->addError( + 'Overriding WordPress globals is prohibited. Found assignment to %s', + $stackPtr, + 'Prohibited', + $data + ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php new file mode 100644 index 000000000..d229cb5e9 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/I18nSniff.php @@ -0,0 +1,789 @@ +phpcsFile->getFilename() + * @link https://youtrack.jetbrains.com/issue/WI-17740 + * + * @var string[]|string + */ + public $text_domain; + + /** + * The I18N functions in use in WP. + * + * @since 0.10.0 + * @since 0.11.0 Changed visibility from public to protected. + * + * @var array => + */ + protected $i18n_functions = array( + 'translate' => 'simple', + '__' => 'simple', + 'esc_attr__' => 'simple', + 'esc_html__' => 'simple', + '_e' => 'simple', + 'esc_attr_e' => 'simple', + 'esc_html_e' => 'simple', + 'translate_with_gettext_context' => 'context', + '_x' => 'context', + '_ex' => 'context', + 'esc_attr_x' => 'context', + 'esc_html_x' => 'context', + '_n' => 'number', + '_nx' => 'number_context', + '_n_noop' => 'noopnumber', + '_nx_noop' => 'noopnumber_context', + ); + + /** + * Toggle whether or not to check for translators comments for text string containing placeholders. + * + * Intended to make this part of the sniff unit testable, but can be used by end-users too, + * though they can just as easily disable this via the sniff code. + * + * @since 0.11.0 + * + * @var bool + */ + public $check_translator_comments = true; + + /** + * Whether or not the `default` text domain is one of the allowed text domains. + * + * @since 0.14.0 + * + * @var bool + */ + private $text_domain_contains_default = false; + + /** + * Whether or not the `default` text domain is the only allowed text domain. + * + * @since 0.14.0 + * + * @var bool + */ + private $text_domain_is_default = false; + + /** + * Groups of functions to restrict. + * + * Example: groups => array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'file_get_contents', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'i18n' => array( + 'functions' => array_keys( $this->i18n_functions ), + ), + 'typos' => array( + 'functions' => array( + '_', + ), + ), + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 1.0.0 Defers to the abstractFunctionRestriction sniff for determining + * whether something is a function call. The logic after that has + * been split off to the `process_matched_token()` method. + * + * @param int $stack_ptr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stack_ptr ) { + + // Reset defaults. + $this->text_domain_contains_default = false; + $this->text_domain_is_default = false; + + // Allow overruling the text_domain set in a ruleset via the command line. + $cl_text_domain = trim( PHPCSHelper::get_config_data( 'text_domain' ) ); + if ( ! empty( $cl_text_domain ) ) { + $this->text_domain = array_filter( array_map( 'trim', explode( ',', $cl_text_domain ) ) ); + } + + $this->text_domain = $this->merge_custom_array( $this->text_domain, array(), false ); + + if ( ! empty( $this->text_domain ) ) { + if ( \in_array( 'default', $this->text_domain, true ) ) { + $this->text_domain_contains_default = true; + if ( \count( $this->text_domain ) === 1 ) { + $this->text_domain_is_default = true; + } + } + } + + // Prevent exclusion of the i18n group. + $this->exclude = array(); + + parent::process_token( $stack_ptr ); + } + + /** + * Process a matched token. + * + * @since 1.0.0 Logic split off from the `process_token()` method. + * + * @param int $stack_ptr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process_matched_token( $stack_ptr, $group_name, $matched_content ) { + + $func_open_paren_token = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stack_ptr + 1 ), null, true ); + if ( false === $func_open_paren_token + || \T_OPEN_PARENTHESIS !== $this->tokens[ $func_open_paren_token ]['code'] + || ! isset( $this->tokens[ $func_open_paren_token ]['parenthesis_closer'] ) + ) { + // Live coding, parse error or not a function call. + return; + } + + if ( 'typos' === $group_name && '_' === $matched_content ) { + $this->phpcsFile->addError( 'Found single-underscore "_()" function when double-underscore expected.', $stack_ptr, 'SingleUnderscoreGetTextFunction' ); + return; + } + + if ( \in_array( $matched_content, array( 'translate', 'translate_with_gettext_context' ), true ) ) { + $this->phpcsFile->addWarning( 'Use of the "%s()" function is reserved for low-level API usage.', $stack_ptr, 'LowLevelTranslationFunction', array( $matched_content ) ); + } + + $arguments_tokens = array(); + $argument_tokens = array(); + $tokens = $this->tokens; + + // Look at arguments. + for ( $i = ( $func_open_paren_token + 1 ); $i < $this->tokens[ $func_open_paren_token ]['parenthesis_closer']; $i++ ) { + $this_token = $this->tokens[ $i ]; + $this_token['token_index'] = $i; + if ( isset( Tokens::$emptyTokens[ $this_token['code'] ] ) ) { + continue; + } + if ( \T_COMMA === $this_token['code'] ) { + $arguments_tokens[] = $argument_tokens; + $argument_tokens = array(); + continue; + } + + // Merge consecutive single or double quoted strings (when they span multiple lines). + if ( isset( Tokens::$textStringTokens[ $this_token['code'] ] ) ) { + for ( $j = ( $i + 1 ); $j < $this->tokens[ $func_open_paren_token ]['parenthesis_closer']; $j++ ) { + if ( $this_token['code'] === $this->tokens[ $j ]['code'] ) { + $this_token['content'] .= $this->tokens[ $j ]['content']; + $i = $j; + } else { + break; + } + } + } + $argument_tokens[] = $this_token; + + // Include everything up to and including the parenthesis_closer if this token has one. + if ( ! empty( $this_token['parenthesis_closer'] ) ) { + for ( $j = ( $i + 1 ); $j <= $this_token['parenthesis_closer']; $j++ ) { + $tokens[ $j ]['token_index'] = $j; + $argument_tokens[] = $tokens[ $j ]; + } + $i = $this_token['parenthesis_closer']; + } + } + + if ( ! empty( $argument_tokens ) ) { + $arguments_tokens[] = $argument_tokens; + } + unset( $argument_tokens ); + + $argument_assertions = array(); + if ( 'simple' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'text', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'context' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'text', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'context', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'number' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + array_shift( $arguments_tokens ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'number_context' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + array_shift( $arguments_tokens ); + $argument_assertions[] = array( + 'arg_name' => 'context', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'noopnumber' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } elseif ( 'noopnumber_context' === $this->i18n_functions[ $matched_content ] ) { + $argument_assertions[] = array( + 'arg_name' => 'single', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'plural', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'context', + 'tokens' => array_shift( $arguments_tokens ), + ); + $argument_assertions[] = array( + 'arg_name' => 'domain', + 'tokens' => array_shift( $arguments_tokens ), + ); + } + + if ( ! empty( $arguments_tokens ) ) { + $this->phpcsFile->addError( 'Too many arguments for function "%s".', $func_open_paren_token, 'TooManyFunctionArgs', array( $matched_content ) ); + } + + foreach ( $argument_assertions as $argument_assertion_context ) { + if ( empty( $argument_assertion_context['tokens'][0] ) ) { + $argument_assertion_context['stack_ptr'] = $func_open_paren_token; + } else { + $argument_assertion_context['stack_ptr'] = $argument_assertion_context['tokens'][0]['token_index']; + } + $this->check_argument_tokens( $argument_assertion_context ); + } + + /* + * For _n*() calls, compare the singular and plural strings. + * If either of the arguments is missing, empty or has more than 1 token, skip out. + * An error for that will already have been reported via the `check_argument_tokens()` method. + */ + if ( false !== strpos( $this->i18n_functions[ $matched_content ], 'number' ) + && isset( $argument_assertions[0]['tokens'], $argument_assertions[1]['tokens'] ) + && count( $argument_assertions[0]['tokens'] ) === 1 + && count( $argument_assertions[1]['tokens'] ) === 1 + ) { + $single_context = $argument_assertions[0]; + $plural_context = $argument_assertions[1]; + + $this->compare_single_and_plural_arguments( $stack_ptr, $single_context, $plural_context ); + } + + if ( true === $this->check_translator_comments ) { + $this->check_for_translator_comment( $stack_ptr, $argument_assertions ); + } + } + + /** + * Check if supplied tokens represent a translation text string literal. + * + * @param array $context Context (@todo needs better description). + * @return bool + */ + protected function check_argument_tokens( $context ) { + $stack_ptr = $context['stack_ptr']; + $tokens = $context['tokens']; + $arg_name = $context['arg_name']; + $is_error = empty( $context['warning'] ); + $content = isset( $tokens[0] ) ? $tokens[0]['content'] : ''; + + if ( empty( $tokens ) || 0 === \count( $tokens ) ) { + $code = $this->string_to_errorcode( 'MissingArg' . ucfirst( $arg_name ) ); + if ( 'domain' !== $arg_name ) { + $this->addMessage( 'Missing $%s arg.', $stack_ptr, $is_error, $code, array( $arg_name ) ); + return false; + } + + // Ok, we're examining a text domain, now deal correctly with the 'default' text domain. + if ( true === $this->text_domain_is_default ) { + return true; + } + + if ( true === $this->text_domain_contains_default ) { + $this->phpcsFile->addWarning( + 'Missing $%s arg. If this text string is supposed to use a WP Core translation, use the "default" text domain.', + $stack_ptr, + $code . 'Default', + array( $arg_name ) + ); + } elseif ( ! empty( $this->text_domain ) ) { + $this->addMessage( 'Missing $%s arg.', $stack_ptr, $is_error, $code, array( $arg_name ) ); + } + + return false; + } + + if ( \count( $tokens ) > 1 ) { + $contents = ''; + foreach ( $tokens as $token ) { + $contents .= $token['content']; + } + $code = $this->string_to_errorcode( 'NonSingularStringLiteral' . ucfirst( $arg_name ) ); + $this->addMessage( 'The $%s arg must be a single string literal, not "%s".', $stack_ptr, $is_error, $code, array( $arg_name, $contents ) ); + return false; + } + + if ( \in_array( $arg_name, array( 'text', 'single', 'plural' ), true ) ) { + $this->check_text( $context ); + } + + if ( \T_DOUBLE_QUOTED_STRING === $tokens[0]['code'] || \T_HEREDOC === $tokens[0]['code'] ) { + $interpolated_variables = $this->get_interpolated_variables( $content ); + foreach ( $interpolated_variables as $interpolated_variable ) { + $code = $this->string_to_errorcode( 'InterpolatedVariable' . ucfirst( $arg_name ) ); + $this->addMessage( 'The $%s arg must not contain interpolated variables. Found "$%s".', $stack_ptr, $is_error, $code, array( $arg_name, $interpolated_variable ) ); + } + if ( ! empty( $interpolated_variables ) ) { + return false; + } + } + + if ( isset( Tokens::$textStringTokens[ $tokens[0]['code'] ] ) ) { + if ( 'domain' === $arg_name && ! empty( $this->text_domain ) ) { + $stripped_content = $this->strip_quotes( $content ); + + if ( ! \in_array( $stripped_content, $this->text_domain, true ) ) { + $this->addMessage( + 'Mismatched text domain. Expected \'%s\' but got %s.', + $stack_ptr, + $is_error, + 'TextDomainMismatch', + array( implode( "' or '", $this->text_domain ), $content ) + ); + return false; + } + + if ( true === $this->text_domain_is_default && 'default' === $stripped_content ) { + $fixable = false; + $error = 'No need to supply the text domain when the only accepted text domain is "default".'; + $error_code = 'SuperfluousDefaultTextDomain'; + + if ( $tokens[0]['token_index'] === $stack_ptr ) { + $prev = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $stack_ptr - 1 ), null, true ); + if ( false !== $prev && \T_COMMA === $this->tokens[ $prev ]['code'] ) { + $fixable = true; + } + } + + if ( false === $fixable ) { + $this->phpcsFile->addWarning( $error, $stack_ptr, $error_code ); + return false; + } + + $fix = $this->phpcsFile->addFixableWarning( $error, $stack_ptr, $error_code ); + if ( true === $fix ) { + // Remove preceeding comma, whitespace and the text domain token. + $this->phpcsFile->fixer->beginChangeset(); + for ( $i = $prev; $i <= $stack_ptr; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + $this->phpcsFile->fixer->endChangeset(); + } + + return false; + } + } + + return true; + } + + $code = $this->string_to_errorcode( 'NonSingularStringLiteral' . ucfirst( $arg_name ) ); + $this->addMessage( 'The $%s arg must be a single string literal, not "%s".', $stack_ptr, $is_error, $code, array( $arg_name, $content ) ); + return false; + } + + /** + * Check for inconsistencies between single and plural arguments. + * + * @param int $stack_ptr The position of the current token in the stack. + * @param array $single_context Single context (@todo needs better description). + * @param array $plural_context Plural context (@todo needs better description). + * @return void + */ + protected function compare_single_and_plural_arguments( $stack_ptr, $single_context, $plural_context ) { + $single_content = $single_context['tokens'][0]['content']; + $plural_content = $plural_context['tokens'][0]['content']; + + preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $single_content, $single_placeholders ); + $single_placeholders = $single_placeholders[0]; + + preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $plural_content, $plural_placeholders ); + $plural_placeholders = $plural_placeholders[0]; + + // English conflates "singular" with "only one", described in the codex: + // https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals . + if ( \count( $single_placeholders ) < \count( $plural_placeholders ) ) { + $error_string = 'Missing singular placeholder, needed for some languages. See https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals'; + $single_index = $single_context['tokens'][0]['token_index']; + + $this->phpcsFile->addError( $error_string, $single_index, 'MissingSingularPlaceholder' ); + } + + // Reordering is fine, but mismatched placeholders is probably wrong. + sort( $single_placeholders ); + sort( $plural_placeholders ); + + if ( $single_placeholders !== $plural_placeholders ) { + $this->phpcsFile->addWarning( 'Mismatched placeholders is probably an error', $stack_ptr, 'MismatchedPlaceholders' ); + } + } + + /** + * Check the string itself for problems. + * + * @param array $context Context (@todo needs better description). + * @return void + */ + protected function check_text( $context ) { + $stack_ptr = $context['stack_ptr']; + $arg_name = $context['arg_name']; + $content = $context['tokens'][0]['content']; + $is_error = empty( $context['warning'] ); + + // UnorderedPlaceholders: Check for multiple unordered placeholders. + $unordered_matches_count = preg_match_all( self::UNORDERED_SPRINTF_PLACEHOLDER_REGEX, $content, $unordered_matches ); + $unordered_matches = $unordered_matches[0]; + $all_matches_count = preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $content, $all_matches ); + + if ( $unordered_matches_count > 0 && $unordered_matches_count !== $all_matches_count && $all_matches_count > 1 ) { + $code = $this->string_to_errorcode( 'MixedOrderedPlaceholders' . ucfirst( $arg_name ) ); + $this->phpcsFile->addError( + 'Multiple placeholders should be ordered. Mix of ordered and non-ordered placeholders found. Found: %s.', + $stack_ptr, + $code, + array( implode( ', ', $all_matches[0] ) ) + ); + + } elseif ( $unordered_matches_count >= 2 ) { + $code = $this->string_to_errorcode( 'UnorderedPlaceholders' . ucfirst( $arg_name ) ); + + $suggestions = array(); + $replace_regexes = array(); + $replacements = array(); + for ( $i = 0; $i < $unordered_matches_count; $i++ ) { + $to_insert = ( $i + 1 ); + $to_insert .= ( '"' !== $content[0] ) ? '$' : '\$'; + $suggestions[ $i ] = substr_replace( $unordered_matches[ $i ], $to_insert, 1, 0 ); + + // Prepare the strings for use a regex. + $replace_regexes[ $i ] = '`\Q' . $unordered_matches[ $i ] . '\E`'; + // Note: the initial \\ is a literal \, the four \ in the replacement translate to also to a literal \. + $replacements[ $i ] = str_replace( '\\', '\\\\', $suggestions[ $i ] ); + // Note: the $ needs escaping to prevent numeric sequences after the $ being interpreted as match replacements. + $replacements[ $i ] = str_replace( '$', '\\$', $replacements[ $i ] ); + } + + $fix = $this->addFixableMessage( + 'Multiple placeholders should be ordered. Expected \'%s\', but got %s.', + $stack_ptr, + $is_error, + $code, + array( implode( ', ', $suggestions ), implode( ', ', $unordered_matches ) ) + ); + + if ( true === $fix ) { + $fixed_str = preg_replace( $replace_regexes, $replacements, $content, 1 ); + + $this->phpcsFile->fixer->replaceToken( $stack_ptr, $fixed_str ); + } + } + + /* + * NoEmptyStrings. + * + * Strip placeholders and surrounding quotes. + */ + $content_without_quotes = trim( $this->strip_quotes( $content ) ); + $non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $content_without_quotes ); + + if ( '' === $non_placeholder_content ) { + $this->phpcsFile->addError( 'Strings should have translatable content', $stack_ptr, 'NoEmptyStrings' ); + return; + } + + /* + * NoHtmlWrappedStrings + * + * Strip surrounding quotes. + */ + $reader = new \XMLReader(); + $reader->XML( $content_without_quotes, 'UTF-8', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_NOWARNING ); + + // Is the first node an HTML element? + if ( ! $reader->read() || \XMLReader::ELEMENT !== $reader->nodeType ) { + return; + } + + // If the opening HTML element includes placeholders in its attributes, we don't warn. + // E.g. ''. + $i = 0; + while ( $attr = $reader->getAttributeNo( $i ) ) { + if ( preg_match( self::SPRINTF_PLACEHOLDER_REGEX, $attr ) === 1 ) { + return; + } + + ++$i; + } + + // We don't flag strings wrapped in `...`, as the link target might actually need localization. + if ( 'a' === $reader->name && $reader->getAttribute( 'href' ) ) { + return; + } + + // Does the entire string only consist of this HTML node? + if ( $reader->readOuterXml() === $content_without_quotes ) { + $this->phpcsFile->addWarning( 'Strings should not be wrapped in HTML', $stack_ptr, 'NoHtmlWrappedStrings' ); + } + } + + /** + * Check for the presence of a translators comment if one of the text strings contains a placeholder. + * + * @param int $stack_ptr The position of the gettext call token in the stack. + * @param array $args The function arguments. + * @return void + */ + protected function check_for_translator_comment( $stack_ptr, $args ) { + foreach ( $args as $arg ) { + if ( false === \in_array( $arg['arg_name'], array( 'text', 'single', 'plural' ), true ) ) { + continue; + } + + if ( empty( $arg['tokens'] ) ) { + continue; + } + + foreach ( $arg['tokens'] as $token ) { + if ( empty( $token['content'] ) ) { + continue; + } + + if ( preg_match( self::SPRINTF_PLACEHOLDER_REGEX, $token['content'], $placeholders ) < 1 ) { + // No placeholders found. + continue; + } + + $previous_comment = $this->phpcsFile->findPrevious( Tokens::$commentTokens, ( $stack_ptr - 1 ) ); + + if ( false !== $previous_comment ) { + /* + * Check that the comment is either on the line before the gettext call or + * if it's not, that there is only whitespace between. + */ + $correctly_placed = false; + + if ( ( $this->tokens[ $previous_comment ]['line'] + 1 ) === $this->tokens[ $stack_ptr ]['line'] ) { + $correctly_placed = true; + } else { + $next_non_whitespace = $this->phpcsFile->findNext( \T_WHITESPACE, ( $previous_comment + 1 ), $stack_ptr, true ); + if ( false === $next_non_whitespace || $this->tokens[ $next_non_whitespace ]['line'] === $this->tokens[ $stack_ptr ]['line'] ) { + // No non-whitespace found or next non-whitespace is on same line as gettext call. + $correctly_placed = true; + } + unset( $next_non_whitespace ); + } + + /* + * Check that the comment starts with 'translators:'. + */ + if ( true === $correctly_placed ) { + + if ( \T_COMMENT === $this->tokens[ $previous_comment ]['code'] ) { + $comment_text = trim( $this->tokens[ $previous_comment ]['content'] ); + + // If it's multi-line /* */ comment, collect all the parts. + if ( '*/' === substr( $comment_text, -2 ) && '/*' !== substr( $comment_text, 0, 2 ) ) { + for ( $i = ( $previous_comment - 1 ); 0 <= $i; $i-- ) { + if ( \T_COMMENT !== $this->tokens[ $i ]['code'] ) { + break; + } + + $comment_text = trim( $this->tokens[ $i ]['content'] ) . $comment_text; + } + } + + if ( true === $this->is_translators_comment( $comment_text ) ) { + // Comment is ok. + return; + } + } elseif ( \T_DOC_COMMENT_CLOSE_TAG === $this->tokens[ $previous_comment ]['code'] ) { + // If it's docblock comment (wrong style) make sure that it's a translators comment. + $db_start = $this->phpcsFile->findPrevious( \T_DOC_COMMENT_OPEN_TAG, ( $previous_comment - 1 ) ); + $db_first_text = $this->phpcsFile->findNext( \T_DOC_COMMENT_STRING, ( $db_start + 1 ), $previous_comment ); + + if ( true === $this->is_translators_comment( $this->tokens[ $db_first_text ]['content'] ) ) { + $this->phpcsFile->addWarning( + 'A "translators:" comment must be a "/* */" style comment. Docblock comments will not be picked up by the tools to generate a ".pot" file.', + $stack_ptr, + 'TranslatorsCommentWrongStyle' + ); + return; + } + } + } + } + + // Found placeholders but no translators comment. + $this->phpcsFile->addWarning( + 'A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.', + $stack_ptr, + 'MissingTranslatorsComment' + ); + return; + } + } + } + + /** + * Check if a (collated) comment string starts with 'translators:'. + * + * @since 0.11.0 + * + * @param string $content Comment string content. + * @return bool + */ + private function is_translators_comment( $content ) { + if ( preg_match( '`^(?:(?://|/\*{1,2}) )?translators:`i', $content, $matches ) === 1 ) { + return true; + } + return false; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php new file mode 100644 index 000000000..968a0342b --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/PostsPerPageSniff.php @@ -0,0 +1,78 @@ + array( + 'type' => 'warning', + 'keys' => array( + 'posts_per_page', + 'numberposts', + ), + ), + ); + } + + /** + * Callback to process each confirmed key, to check value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + $this->posts_per_page = (int) $this->posts_per_page; + + if ( $val > $this->posts_per_page ) { + return 'Detected high pagination limit, `%s` is set to `%s`'; + } + + return false; + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php new file mode 100644 index 000000000..f376c5e3a --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WP/TimezoneChangeSniff.php @@ -0,0 +1,88 @@ + false, + 'FoundPropertyForDeprecatedSniff' => false, + ); + + /** + * Don't use. + * + * @deprecated 2.2.0 + * + * @return array + */ + public function getGroups() { + $groups = parent::getGroups(); + return array( 'timezone_change' => $groups['timezone_change'] ); + } + + /** + * Don't use. + * + * @since 2.2.0 Added to allow for throwing the deprecation notices. + * @deprecated 2.2.0 + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void|int + */ + public function process_token( $stackPtr ) { + if ( false === $this->thrown['DeprecatedSniff'] ) { + $this->thrown['DeprecatedSniff'] = $this->phpcsFile->addWarning( + 'The "WordPress.WP.TimezoneChange" sniff has been deprecated. Use the "WordPress.DateTime.RestrictedFunctions" sniff instead. Please update your custom ruleset.', + 0, + 'DeprecatedSniff' + ); + } + + if ( ! empty( $this->exclude ) + && false === $this->thrown['FoundPropertyForDeprecatedSniff'] + ) { + $this->thrown['FoundPropertyForDeprecatedSniff'] = $this->phpcsFile->addWarning( + 'The "WordPress.WP.TimezoneChange" sniff has been deprecated. Use the "WordPress.DateTime.RestrictedFunctions" sniff instead. "exclude" property setting found. Please update your custom ruleset.', + 0, + 'FoundPropertyForDeprecatedSniff' + ); + } + + return parent::process_token( $stackPtr ); + } +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php new file mode 100644 index 000000000..41494b91f --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php @@ -0,0 +1,62 @@ +tokens[ ( $stackPtr - 1 ) ]['code'] + && \T_ELLIPSIS !== $this->tokens[ ( $stackPtr - 1 ) ]['code'] + ) { + $error = 'No space before opening casting parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $stackPtr, ' ' ); + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..5f7b9a3ca --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -0,0 +1,572 @@ + true, + \T_CLOSURE => true, + \T_DO => true, + \T_ELSE => true, + \T_TRY => true, + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_IF, + \T_WHILE, + \T_FOREACH, + \T_FOR, + \T_SWITCH, + \T_DO, + \T_ELSE, + \T_ELSEIF, + \T_FUNCTION, + \T_CLOSURE, + \T_USE, + \T_TRY, + \T_CATCH, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return void + */ + public function process_token( $stackPtr ) { + $this->spaces_before_closure_open_paren = (int) $this->spaces_before_closure_open_paren; + + if ( isset( $this->tokens[ ( $stackPtr + 1 ) ] ) && \T_WHITESPACE !== $this->tokens[ ( $stackPtr + 1 ) ]['code'] + && ! ( \T_ELSE === $this->tokens[ $stackPtr ]['code'] && \T_COLON === $this->tokens[ ( $stackPtr + 1 ) ]['code'] ) + && ! ( \T_CLOSURE === $this->tokens[ $stackPtr ]['code'] + && 0 >= $this->spaces_before_closure_open_paren ) + ) { + $error = 'Space after opening control structure is required'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfterStructureOpen' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $stackPtr, ' ' ); + } + } + + if ( ! isset( $this->tokens[ $stackPtr ]['scope_closer'] ) ) { + + if ( \T_USE === $this->tokens[ $stackPtr ]['code'] && 'closure' === $this->get_use_type( $stackPtr ) ) { + $scopeOpener = $this->phpcsFile->findNext( \T_OPEN_CURLY_BRACKET, ( $stackPtr + 1 ) ); + $scopeCloser = $this->tokens[ $scopeOpener ]['scope_closer']; + } elseif ( \T_WHILE !== $this->tokens[ $stackPtr ]['code'] ) { + return; + } + } else { + $scopeOpener = $this->tokens[ $stackPtr ]['scope_opener']; + $scopeCloser = $this->tokens[ $stackPtr ]['scope_closer']; + } + + // Alternative syntax. + if ( isset( $scopeOpener ) && \T_COLON === $this->tokens[ $scopeOpener ]['code'] ) { + + if ( 'required' === $this->space_before_colon ) { + + if ( \T_WHITESPACE !== $this->tokens[ ( $scopeOpener - 1 ) ]['code'] ) { + $error = 'Space between opening control structure and T_COLON is required'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceBetweenStructureColon' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); + } + } + } elseif ( 'forbidden' === $this->space_before_colon ) { + + if ( \T_WHITESPACE === $this->tokens[ ( $scopeOpener - 1 ) ]['code'] ) { + $error = 'Extra space between opening control structure and T_COLON found'; + $fix = $this->phpcsFile->addFixableError( $error, ( $scopeOpener - 1 ), 'SpaceBetweenStructureColon' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $scopeOpener - 1 ), '' ); + } + } + } + } + + $parenthesisOpener = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + // If this is a function declaration. + if ( \T_FUNCTION === $this->tokens[ $stackPtr ]['code'] ) { + + if ( \T_STRING === $this->tokens[ $parenthesisOpener ]['code'] ) { + + $function_name_ptr = $parenthesisOpener; + + } elseif ( \T_BITWISE_AND === $this->tokens[ $parenthesisOpener ]['code'] ) { + + // This function returns by reference (function &function_name() {}). + $parenthesisOpener = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $parenthesisOpener + 1 ), + null, + true + ); + $function_name_ptr = $parenthesisOpener; + } + + if ( isset( $function_name_ptr ) ) { + $parenthesisOpener = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $parenthesisOpener + 1 ), + null, + true + ); + + // Checking this: function my_function[*](...) {}. + if ( ( $function_name_ptr + 1 ) !== $parenthesisOpener ) { + + $error = 'Space between function name and opening parenthesis is prohibited.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'SpaceBeforeFunctionOpenParenthesis', + $this->tokens[ ( $function_name_ptr + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $function_name_ptr + 1 ), '' ); + } + } + } + } elseif ( \T_CLOSURE === $this->tokens[ $stackPtr ]['code'] ) { + + // Check if there is a use () statement. + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { + + $usePtr = $this->phpcsFile->findNext( + Tokens::$emptyTokens, + ( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] + 1 ), + null, + true, + null, + true + ); + + // If it is, we set that as the "scope opener". + if ( \T_USE === $this->tokens[ $usePtr ]['code'] ) { + $scopeOpener = $usePtr; + } + } + } + + if ( \T_COLON !== $this->tokens[ $parenthesisOpener ]['code'] + && \T_FUNCTION !== $this->tokens[ $stackPtr ]['code'] + ) { + + if ( \T_CLOSURE === $this->tokens[ $stackPtr ]['code'] + && 0 === $this->spaces_before_closure_open_paren + ) { + + if ( ( $stackPtr + 1 ) !== $parenthesisOpener ) { + // Checking this: function[*](...) {}. + $error = 'Space before closure opening parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'SpaceBeforeClosureOpenParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), '' ); + } + } + } elseif ( + ( + \T_CLOSURE !== $this->tokens[ $stackPtr ]['code'] + || 1 === $this->spaces_before_closure_open_paren + ) + && ( $stackPtr + 1 ) === $parenthesisOpener + ) { + + // Checking this: if[*](...) {}. + $error = 'No space before opening parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $stackPtr, ' ' ); + } + } + } + + if ( \T_WHITESPACE === $this->tokens[ ( $stackPtr + 1 ) ]['code'] + && ' ' !== $this->tokens[ ( $stackPtr + 1 ) ]['content'] + ) { + // Checking this: if [*](...) {}. + $error = 'Expected exactly one space before opening parenthesis; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceBeforeOpenParenthesis', + $this->tokens[ ( $stackPtr + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), ' ' ); + } + } + + if ( \T_CLOSE_PARENTHESIS !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + if ( \T_WHITESPACE !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + // Checking this: $value = my_function([*]...). + $error = 'No space after opening parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfterOpenParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContent( $parenthesisOpener, ' ' ); + } + } elseif ( ( ' ' !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] + && "\n" !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] + && "\r\n" !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] ) + && ! isset( $this->ignore_extra_space_after_open_paren[ $this->tokens[ $stackPtr ]['code'] ] ) + ) { + // Checking this: if ([*]...) {}. + $error = 'Expected exactly one space after opening parenthesis; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceAfterOpenParenthesis', + $this->tokens[ ( $parenthesisOpener + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $parenthesisOpener + 1 ), ' ' ); + } + } + } + + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { + + $parenthesisCloser = $this->tokens[ $parenthesisOpener ]['parenthesis_closer']; + + if ( \T_CLOSE_PARENTHESIS !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + + // Checking this: if (...[*]) {}. + if ( \T_WHITESPACE !== $this->tokens[ ( $parenthesisCloser - 1 ) ]['code'] ) { + $error = 'No space before closing parenthesis is prohibited'; + $fix = $this->phpcsFile->addFixableError( $error, $parenthesisCloser, 'NoSpaceBeforeCloseParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $parenthesisCloser, ' ' ); + } + } elseif ( ' ' !== $this->tokens[ ( $parenthesisCloser - 1 ) ]['content'] ) { + $prevNonEmpty = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $parenthesisCloser - 1 ), null, true ); + if ( $this->tokens[ ( $parenthesisCloser ) ]['line'] === $this->tokens[ ( $prevNonEmpty + 1 ) ]['line'] ) { + $error = 'Expected exactly one space before closing parenthesis; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceBeforeCloseParenthesis', + $this->tokens[ ( $parenthesisCloser - 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $parenthesisCloser - 1 ), ' ' ); + } + } + } + + if ( \T_WHITESPACE !== $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ! ( // Do NOT flag : immediately following ) for return types declarations. + \T_COLON === $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ( isset( $this->tokens[ $parenthesisCloser ]['parenthesis_owner'] ) === false + || in_array( $this->tokens[ $this->tokens[ $parenthesisCloser ]['parenthesis_owner'] ]['code'], array( \T_FUNCTION, \T_CLOSURE ), true ) ) + ) + && ( isset( $scopeOpener ) && \T_COLON !== $this->tokens[ $scopeOpener ]['code'] ) + ) { + $error = 'Space between opening control structure and closing parenthesis is required'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceAfterCloseParenthesis' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); + } + } + } + + // Ignore this for function declarations. Handled by the OpeningFunctionBraceKernighanRitchie sniff. + if ( \T_FUNCTION !== $this->tokens[ $stackPtr ]['code'] + && \T_CLOSURE !== $this->tokens[ $stackPtr ]['code'] + && isset( $this->tokens[ $parenthesisOpener ]['parenthesis_owner'] ) + && ( isset( $scopeOpener ) + && $this->tokens[ $parenthesisCloser ]['line'] !== $this->tokens[ $scopeOpener ]['line'] ) + ) { + $error = 'Opening brace should be on the same line as the declaration'; + $fix = $this->phpcsFile->addFixableError( $error, $parenthesisOpener, 'OpenBraceNotSameLine' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $parenthesisCloser + 1 ); $i < $scopeOpener; $i++ ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->addContent( $parenthesisCloser, ' ' ); + $this->phpcsFile->fixer->endChangeset(); + } + return; + + } elseif ( \T_WHITESPACE === $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ' ' !== $this->tokens[ ( $parenthesisCloser + 1 ) ]['content'] + ) { + + // Checking this: if (...) [*]{}. + $error = 'Expected exactly one space between closing parenthesis and opening control structure; "%s" found.'; + $fix = $this->phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceAfterCloseParenthesis', + $this->tokens[ ( $parenthesisCloser + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->replaceToken( ( $parenthesisCloser + 1 ), ' ' ); + } + } + } + + if ( false !== $this->blank_line_check && isset( $scopeOpener ) ) { + $firstContent = $this->phpcsFile->findNext( \T_WHITESPACE, ( $scopeOpener + 1 ), null, true ); + + // We ignore spacing for some structures that tend to have their own rules. + $ignore = array( + \T_FUNCTION => true, + \T_CLOSURE => true, + \T_DOC_COMMENT_OPEN_TAG => true, + \T_CLOSE_TAG => true, + \T_COMMENT => true, + ); + $ignore += Tokens::$ooScopeTokens; + + if ( ! isset( $ignore[ $this->tokens[ $firstContent ]['code'] ] ) + && $this->tokens[ $firstContent ]['line'] > ( $this->tokens[ $scopeOpener ]['line'] + 1 ) + ) { + $error = 'Blank line found at start of control structure'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeOpener, 'BlankLineAfterStart' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $scopeOpener + 1 ); $i < $firstContent; $i++ ) { + if ( $this->tokens[ $i ]['line'] === $this->tokens[ $firstContent ]['line'] ) { + break; + } + $this->phpcsFile->fixer->replaceToken( $i, '' ); + } + + $this->phpcsFile->fixer->addNewline( $scopeOpener ); + $this->phpcsFile->fixer->endChangeset(); + } + } + + if ( $firstContent !== $scopeCloser ) { + $lastContent = $this->phpcsFile->findPrevious( \T_WHITESPACE, ( $scopeCloser - 1 ), null, true ); + + $lastNonEmptyContent = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $scopeCloser - 1 ), null, true ); + + $checkToken = $lastContent; + if ( isset( $this->tokens[ $lastNonEmptyContent ]['scope_condition'] ) ) { + $checkToken = $this->tokens[ $lastNonEmptyContent ]['scope_condition']; + } + + if ( ! isset( $ignore[ $this->tokens[ $checkToken ]['code'] ] ) + && $this->tokens[ $lastContent ]['line'] <= ( $this->tokens[ $scopeCloser ]['line'] - 2 ) + ) { + for ( $i = ( $scopeCloser - 1 ); $i > $lastContent; $i-- ) { + if ( $this->tokens[ $i ]['line'] < $this->tokens[ $scopeCloser ]['line'] + && \T_OPEN_TAG !== $this->tokens[ $firstContent ]['code'] + ) { + // TODO: Reporting error at empty line won't highlight it in IDE. + $error = 'Blank line found at end of control structure'; + $fix = $this->phpcsFile->addFixableError( $error, $i, 'BlankLineBeforeEnd' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + for ( $j = ( $lastContent + 1 ); $j < $scopeCloser; $j++ ) { + if ( $this->tokens[ $j ]['line'] === $this->tokens[ $scopeCloser ]['line'] ) { + break; + } + $this->phpcsFile->fixer->replaceToken( $j, '' ); + } + + /* + * PHPCS annotations, like normal inline comments, are tokenized including + * the new line at the end, so don't add any extra as it would cause a fixer + * conflict. + */ + if ( \T_COMMENT !== $this->tokens[ $lastContent ]['code'] + && ! isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $lastContent ]['code'] ] ) ) { + $this->phpcsFile->fixer->addNewlineBefore( $j ); + } + + $this->phpcsFile->fixer->endChangeset(); + } + break; + } + } + } + } + unset( $ignore ); + } + + if ( ! isset( $scopeCloser ) || true !== $this->blank_line_after_check ) { + return; + } + + // {@internal This is just for the blank line check. Only whitespace should be considered, + // not "other" empty tokens.}} + $trailingContent = $this->phpcsFile->findNext( \T_WHITESPACE, ( $scopeCloser + 1 ), null, true ); + if ( false === $trailingContent ) { + return; + } + + if ( \T_COMMENT === $this->tokens[ $trailingContent ]['code'] + || isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $trailingContent ]['code'] ] ) + ) { + // Special exception for code where the comment about + // an ELSE or ELSEIF is written between the control structures. + $nextCode = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $scopeCloser + 1 ), null, true ); + + if ( \T_ELSE === $this->tokens[ $nextCode ]['code'] || \T_ELSEIF === $this->tokens[ $nextCode ]['code'] ) { + $trailingContent = $nextCode; + } + + // Move past end comments. + if ( $this->tokens[ $trailingContent ]['line'] === $this->tokens[ $scopeCloser ]['line'] ) { + if ( preg_match( '`^//[ ]?end`i', $this->tokens[ $trailingContent ]['content'], $matches ) > 0 ) { + $scopeCloser = $trailingContent; + $trailingContent = $this->phpcsFile->findNext( \T_WHITESPACE, ( $trailingContent + 1 ), null, true ); + } + } + } + + if ( \T_ELSE === $this->tokens[ $trailingContent ]['code'] && \T_IF === $this->tokens[ $stackPtr ]['code'] ) { + // IF with ELSE. + return; + } + + if ( \T_WHILE === $this->tokens[ $trailingContent ]['code'] && \T_DO === $this->tokens[ $stackPtr ]['code'] ) { + // DO with WHILE. + return; + } + + if ( \T_CLOSE_TAG === $this->tokens[ $trailingContent ]['code'] ) { + // At the end of the script or embedded code. + return; + } + + if ( isset( $this->tokens[ $trailingContent ]['scope_condition'] ) + && \T_CLOSE_CURLY_BRACKET === $this->tokens[ $trailingContent ]['code'] + ) { + // Another control structure's closing brace. + $owner = $this->tokens[ $trailingContent ]['scope_condition']; + if ( \in_array( $this->tokens[ $owner ]['code'], array( \T_FUNCTION, \T_CLOSURE, \T_CLASS, \T_ANON_CLASS, \T_INTERFACE, \T_TRAIT ), true ) ) { + // The next content is the closing brace of a function, class, interface or trait + // so normal function/class rules apply and we can ignore it. + return; + } + + if ( ( $this->tokens[ $scopeCloser ]['line'] + 1 ) !== $this->tokens[ $trailingContent ]['line'] ) { + // TODO: Won't cover following case: "} echo 'OK';". + $error = 'Blank line found after control structure'; + $fix = $this->phpcsFile->addFixableError( $error, $scopeCloser, 'BlankLineAfterEnd' ); + + if ( true === $fix ) { + $this->phpcsFile->fixer->beginChangeset(); + + $i = ( $scopeCloser + 1 ); + while ( $this->tokens[ $i ]['line'] !== $this->tokens[ $trailingContent ]['line'] ) { + $this->phpcsFile->fixer->replaceToken( $i, '' ); + $i++; + } + + // TODO: Instead a separate error should be triggered when content comes right after closing brace. + if ( \T_COMMENT !== $this->tokens[ $scopeCloser ]['code'] + && isset( Tokens::$phpcsCommentTokens[ $this->tokens[ $scopeCloser ]['code'] ] ) === false + ) { + $this->phpcsFile->fixer->addNewlineBefore( $trailingContent ); + } + $this->phpcsFile->fixer->endChangeset(); + } + } + } + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php new file mode 100644 index 000000000..c20a4d33e --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/DisallowInlineTabsSniff.php @@ -0,0 +1,104 @@ +tab_width ) ) { + $this->tab_width = PHPCSHelper::get_tab_width( $this->phpcsFile ); + } + + $check_tokens = array( + \T_WHITESPACE => true, + \T_DOC_COMMENT_WHITESPACE => true, + \T_DOC_COMMENT_STRING => true, + ); + + for ( $i = ( $stackPtr + 1 ); $i < $this->phpcsFile->numTokens; $i++ ) { + // Skip all non-whitespace tokens and skip whitespace at the start of a new line. + if ( ! isset( $check_tokens[ $this->tokens[ $i ]['code'] ] ) || 1 === $this->tokens[ $i ]['column'] ) { + continue; + } + + // If tabs are being converted to spaces by the tokenizer, the + // original content should be checked instead of the converted content. + if ( isset( $this->tokens[ $i ]['orig_content'] ) ) { + $content = $this->tokens[ $i ]['orig_content']; + } else { + $content = $this->tokens[ $i ]['content']; + } + + if ( '' === $content || strpos( $content, "\t" ) === false ) { + continue; + } + + $fix = $this->phpcsFile->addFixableError( + 'Spaces must be used for mid-line alignment; tabs are not allowed', + $i, + 'NonIndentTabsUsed' + ); + if ( true === $fix ) { + if ( isset( $this->tokens[ $i ]['orig_content'] ) ) { + // Use the replacement that PHPCS has already done. + $this->phpcsFile->fixer->replaceToken( $i, $this->tokens[ $i ]['content'] ); + } else { + // Replace tabs with spaces, using an indent of $tab_width. + // Other sniffs can then correct the indent if they need to. + $spaces = str_repeat( ' ', $this->tab_width ); + $newContent = str_replace( "\t", $spaces, $this->tokens[ $i ]['content'] ); + $this->phpcsFile->fixer->replaceToken( $i, $newContent ); + } + } + } + + // Ignore the rest of the file. + return ( $this->phpcsFile->numTokens + 1 ); + } + +} diff --git a/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php new file mode 100644 index 000000000..17e5090c7 --- /dev/null +++ b/kirki-composer/wp-coding-standards/wpcs/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -0,0 +1,64 @@ + + * + * + * + * + * + * + * + * + * @var array + */ + public $ignoreAlignmentTokens = array(); + + /** + * The --tab-width CLI value that is being used. + * + * @var int + */ + private $tab_width; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + \T_OPEN_TAG, + \T_OPEN_TAG_WITH_ECHO, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param int $stackPtr The position of the current token in the stack. + * + * @return int Integer stack pointer to skip the rest of the file. + */ + public function process_token( $stackPtr ) { + if ( ! isset( $this->tab_width ) ) { + $this->tab_width = PHPCSHelper::get_tab_width( $this->phpcsFile ); + } + + // Handle any custom ignore tokens received from a ruleset. + $ignoreAlignmentTokens = $this->merge_custom_array( $this->ignoreAlignmentTokens ); + + $check_tokens = array( + \T_WHITESPACE => true, + \T_INLINE_HTML => true, + \T_DOC_COMMENT_WHITESPACE => true, + \T_COMMENT => true, + ); + $check_tokens += Tokens::$phpcsCommentTokens; + + for ( $i = 0; $i < $this->phpcsFile->numTokens; $i++ ) { + + if ( 1 !== $this->tokens[ $i ]['column'] ) { + continue; + } elseif ( isset( $check_tokens[ $this->tokens[ $i ]['code'] ] ) === false + || ( isset( $this->tokens[ ( $i + 1 ) ] ) + && \T_WHITESPACE === $this->tokens[ ( $i + 1 ) ]['code'] ) + || $this->tokens[ $i ]['content'] === $this->phpcsFile->eolChar + || isset( $ignoreAlignmentTokens[ $this->tokens[ $i ]['type'] ] ) + || ( isset( $this->tokens[ ( $i + 1 ) ] ) + && isset( $ignoreAlignmentTokens[ $this->tokens[ ( $i + 1 ) ]['type'] ] ) ) + ) { + continue; + } + + $spaces = 0; + switch ( $this->tokens[ $i ]['type'] ) { + case 'T_WHITESPACE': + $spaces = ( $this->tokens[ $i ]['length'] % $this->tab_width ); + break; + + case 'T_DOC_COMMENT_WHITESPACE': + $length = $this->tokens[ $i ]['length']; + $spaces = ( $length % $this->tab_width ); + + if ( isset( $this->tokens[ ( $i + 1 ) ] ) + && ( \T_DOC_COMMENT_STAR === $this->tokens[ ( $i + 1 ) ]['code'] + || \T_DOC_COMMENT_CLOSE_TAG === $this->tokens[ ( $i + 1 ) ]['code'] ) + && 0 !== $spaces + ) { + // One alignment space expected before the *. + --$spaces; + } + break; + + case 'T_COMMENT': + case 'T_PHPCS_ENABLE': + case 'T_PHPCS_DISABLE': + case 'T_PHPCS_SET': + case 'T_PHPCS_IGNORE': + case 'T_PHPCS_IGNORE_FILE': + /* + * Indentation whitespace for subsequent lines of multi-line comments + * are tokenized as part of the comment. + */ + $comment = ltrim( $this->tokens[ $i ]['content'] ); + $whitespace = str_replace( $comment, '', $this->tokens[ $i ]['content'] ); + $length = \strlen( $whitespace ); + $spaces = ( $length % $this->tab_width ); + + if ( isset( $comment[0] ) && '*' === $comment[0] && 0 !== $spaces ) { + --$spaces; + } + break; + + case 'T_INLINE_HTML': + if ( $this->tokens[ $i ]['content'] === $this->phpcsFile->eolChar ) { + $spaces = 0; + } else { + /* + * Indentation whitespace for inline HTML is part of the T_INLINE_HTML token. + */ + $content = ltrim( $this->tokens[ $i ]['content'] ); + $whitespace = str_replace( $content, '', $this->tokens[ $i ]['content'] ); + $spaces = ( \strlen( $whitespace ) % $this->tab_width ); + } + + /* + * Prevent triggering on multi-line /*-style inline javascript comments. + * This may cause false negatives as there is no check for being in a + *