bestit/php_codesniffer

此包已被废弃且不再维护。作者建议使用 best-it/php_codesniffer 包代替。

best it 的 PHP_CodeSniffer 规则集和自定义规则。

4.0.0 2023-04-13 09:25 UTC

README

Build Status Build Status Scrutinizer Code Quality Code Coverage

此包包含默认规则集和用于所有 best it 项目的自定义规则。

安装

可以使用以下命令使用 composer 安装我们的 PHP_CodeSniffer 包

composer require best-it/php_codesniffer --dev

请使用版本 1 用于 PHP 7.0!

使用方法

创建一个 PHP_CodeSniffer 配置(phpcs.xml.dist / phpcs.xml)如下所示

<?xml version="1.0"?>
<ruleset name="PROJECT-X">
    <description>The coding standard for project x.</description>

    <!-- Path to best it ruleset. -->
    <rule ref="./vendor/best-it/php_codesniffer/src/Standards/BestIt/ruleset.xml" />

    <!-- Path to directory which are checked. -->
    <file>src/</file>
    <file>tests/</file>
</ruleset>

如果您想针对特殊的 PHP 版本进行嗅探,只需声明一个 "testVersion" 如下所示

<config name="testVersion" value="7.1" />

并在包含我们的规则集后包含

<rule ref="PHPCompatibility" />

(不要忘记 dev-require phpcompatibility/php-compatibility:^9.0。)

执行 PHP_CodeSniffer(路径可能因您的 composer 配置而异)

./vendor/bin/phpcs

我们使用警告来标记人类应该检查但不应导致自动构建失败的事情。如果您想看到警告但得到成功的构建,请使用特殊配置选项 ignore_warnings_on_exit

./vendor/bin/phpcs --config-set ignore_warnings_on_exit 1

或者,如果您只想为单次运行启用此选项

./vendor/bin/phpcs --runtime-set ignore_warnings_on_exit 1

查看原始文档以获取更多信息。

如果您想完全忽略警告,可以提供 cli 参数 n

./vendor/bin/phpcs -n

我们建议不要忽略警告,而只是在手动拉取/合并请求时进行检查。

在 PHPStorm 中使用

如何在我们的最爱 IDE 中使用它?

/File/Settings

  1. Choose executable

  2. Set up inspection

  3. ...然后选择我们的规则集。

使用的嗅探器

BestIt 标准的基础是 PSR-12

嗅探器 描述 可抑制
BestIt.Classes.ModernClassNameReference.ClassNameReferencedViaFunctionCall 您必须使用 ::class 而不是函数。
BestIt.Classes.ModernClassNameReference.ClassNameReferencedViaMagicConstant 您必须使用 ::class 而不是 CLASS
BestIt.Commenting.ClassDoc.DocCommentUcFirst 每个文档注释块应该以 ucfirst 开头。
BestIt.Commenting.ClassDoc.NoLineAfterDocComment 每个文档注释块(摘要或长描述段落)应该以双行结尾。
BestIt.Commenting.ClassDoc.NoSummary 必须有一个摘要。
BestIt.Commenting.ClassDoc.SummaryTooLong 摘要应该在一行内。
BestIt.Commenting.ConstantDoc.DocCommentUcFirst 每个文档注释块应该以 ucfirst 开头。
BestIt.Commenting.ConstantDoc.NoLineAfterDocComment 每个文档注释块(摘要或长描述段落)应该以双行结尾。
BestIt.Commenting.ConstantDoc.NoSummary 必须有一个摘要。
BestIt.Commenting.ConstantDoc.SummaryTooLong 摘要应该在一行内。
BestIt.Commenting.EmptyLinesDoc.EmptyLinesFound 文档块中不得有冗余行。
BestIt.Commenting.FunctionDoc.DocCommentUcFirst 每个文档注释块应该以 ucfirst 开头。
BestIt.Commenting.FunctionDoc.NoLineAfterDocComment 每个文档注释块(摘要或长描述段落)应该以双行结尾。
BestIt.Commenting.FunctionDoc.NoSummary 必须有一个摘要。
BestIt.Commenting.FunctionDoc.SummaryTooLong 摘要应该在一行内。
BestIt.Commenting.PropertyDoc.DocCommentUcFirst 每个文档注释块应该以 ucfirst 开头。
BestIt.Commenting.PropertyDoc.NoLineAfterDocComment 每个文档注释块(摘要或长描述段落)应该以双行结尾。
BestIt.Commenting.PropertyDoc.NoSummary 必须有一个摘要。
BestIt.Commenting.PropertyDoc.SummaryTooLong 摘要应该在一行内。
BestIt.Commenting.RedundantWhitespace.RedundantWhitespace 文档标签周围不得有额外的空格。
BestIt.Comparisons.EmptyArrayForComparison.EmptyArray 您不得创建空数组以检查空数组。
BestIt.Comparisons.EqualOperator.EqualOperatorFound 您必须使用 "Identical" 操作符 (===)。
BestIt.Comparisons.ParasOfNegativeInstanceOf.ParasAroundNegativeInstanceOfMissing 您必须提供负instanceof检查的括号。
BestIt.DocTags.AuthorTag.TagContentFormatInvalid 您必须对您的代码负责,并添加一个作者标签
BestIt.DocTags.DeprecatedTag.MissingDates 缺少日期的错误代码。
BestIt.DocTags.DeprecatedTag.TagContentFormatInvalid 如果您提供了已弃用的标签,您必须提供自何时弃用以及何时删除的信息。
BestIt.DocTags.DisallowedClassTags.TagNotAllowed 您必须在文档注释中避免使用禁止的标签之一。
BestIt.DocTags.DisallowedConstantTags.TagNotAllowed 您必须在文档注释中避免使用禁止的标签之一。
BestIt.DocTags.DisallowedMethodTags.TagNotAllowed 您必须在文档注释中避免使用禁止的标签之一。
BestIt.DocTags.DisallowedPropertyTags.TagNotAllowed 您必须在文档注释中避免使用禁止的标签之一。
BestIt.DocTags.PackageTag.TagContentFormatInvalid 您必须提供特殊的标签格式。
BestIt.DocTags.PackageTag.WrongPackage 如果有命名空间,您必须提供该命名空间作为包标签。
BestIt.DocTags.ParamTag.MissingDesc 您应该为您的参数提供描述。
BestIt.DocTags.ParamTag.MissingType 您必须为您的参数标签提供类型。
BestIt.DocTags.ParamTag.MissingVariable 您的必须有一个与参数标签匹配的变量。
BestIt.DocTags.ParamTag.MissingVariables 如果存在参数标签,您的必须提供参数。
BestIt.DocTags.ParamTag.MixedType 您应该防止混合类型并尝试提供原生类型。
BestIt.DocTags.ParamTag.TagContentFormatInvalid 您必须提供特殊的标签格式。
BestIt.DocTags.RequiredClassTags.TagOccurrenceMax 您必须只提供所需标签的最大数量。例如,每个方法只允许一个返回值。错误记录了每个标签的具体情况。
BestIt.DocTags.RequiredClassTags.TagOccurrenceMin 您必须提供所需标签。错误记录了每个标签的具体情况。
BestIt.DocTags.RequiredMethodTags.TagOccurrenceMax 您必须只提供所需标签的最大数量。例如,每个方法只允许一个返回值。错误记录了每个标签的具体情况。
BestIt.DocTags.RequiredMethodTags.TagOccurrenceMin 您必须提供所需标签。错误记录了每个标签的具体情况。
BestIt.DocTags.RequiredPropertyTags.TagOccurrenceMax 您必须只提供所需标签的最大数量。例如,每个方法只允许一个返回值。错误记录了每个标签的具体情况。
BestIt.DocTags.RequiredPropertyTags.TagOccurrenceMin 您必须提供所需标签。错误记录了每个标签的具体情况。
BestIt.DocTags.TagSorting.MissingNewlineBetweenTags 您应该使用换行符分隔标签组和最终返回值。 按类是yes
BestIt.DocTags.TagSorting.WrongTagSorting 您应该按出现频率排序标签,然后按字母顺序排序,但@return应该是最后一个。 按类是yes
BestIt.DocTags.ThrowsTag.MissingThrowDescription 您应该为您的throw标签提供描述。
BestIt.DocTags.ThrowsTag.TagContentFormatInvalid 您必须提供特殊的标签格式。
BestIt.DocTags.VarTag.TagContentFormatInvalid 您必须为您的var标签提供类型。
BestIt.DocTags.VersionTag.TagContentFormatInvalid 如果您提供了版本标签,您必须以semver 2.0格式提供,格式为Major.Minor.Patch-Version。
BestIt.Formatting.AlphabeticClassContent.SortAlphabetically 您应该按字母顺序排序您的常量、方法和属性。
BestIt.Formatting.AlphabeticallySortedUses.IncorrectlyOrderedUses 您必须按字母顺序提供您的导入,与PSR-12兼容。
(BestIt.Formatting.NoWhitespaceAfterClassOpening.IncorrectEmptyLinesAfterOpeningBrace 在开括号之后不得有行。
(BestIt.Formatting.NoWhitespaceAfterClassOpening.IncorrectEmptyLinesBeforeClosingBrace 在闭括号之前不得有行。
BestIt.Formatting.OpenTag.LineNotEmpty 在打开标签后的下一行必须为空。
BestIt.Formatting.OpenTag.NoSpaceAfterOpenTag 在打开标签之后必须有空白。
BestIt.Formatting.OpenTag.OpenTagNotFirstStatement 在打开标签之后必须有一个空行。
BestIt.Formatting.ReturnTypeHintSpacingSniff.NoSpaceBetweenColonAndTypeHint 在返回类型冒号之后不得有空格。
BestIt.Formatting.ReturnTypeHintSpacingSniff.WhitespaceBeforeColon 在返回类型冒号之前不得有空格。
BestIt.Formatting.TrailingArrayComma.MissingTrailingComma 您必须在多行数组中添加尾随逗号。
BestIt.Formatting.TrailingCommaInDeclaration.MissingTrailingComma 在存在换行的情况下,强制在方法声明中添加尾随逗号。
BestIt.Formatting.TraitUseDeclaration.MultipleTraitsPerDeclaration 您必须在类中导入特性等时,每行只提供一次"使用"。
BestIt.Formatting.UCVFSorting.WrongPosition 您必须按照以下顺序对类、特质、接口等的内容进行排序:T_USE, T_CONST, T_VARIABLE, T_FUNCTION。
BestIt.Functions.FluentSetter.MustReturnThis 每个设置器函数必须返回 $this,除非返回其他内容。
BestIt.Functions.FluentSetter.NoReturnFound 您的方法必须包含一个返回值。
BestIt.Functions.ForbiddenFunctions.Discouraged 您应该不使用 eval。
BestIt.Functions.ForbiddenFunctions.DiscouragedWithAlternative 您应该不使用别名,而是使用原始函数名。
BestIt.Functions.MultipleReturn.MultipleReturnsFound 您应该在每个方法中只使用一个返回值。
BestIt.Functions.NoNamedArguments.DisallowedNamedArgument 您必须不使用命名参数。
BestIt.Functions.NoSimplePropertyMethod.ShouldUseTypedPropertyDirectly 您应该直接使用类型属性,而不是简单的getter-/setter组合。
BestIt.Functions.TrailingCommaInCall.MissingTrailingComma 您必须在多行函数调用后添加尾随逗号。
BestIt.NamingConventions.CamelCaseVariable.NotCamelCase 您必须使用驼峰命名法提供变量,首字母小写。
BestIt.Spacing.ClassMemberSpacing.IncorrectCountOfBlankLinesBetweenMembers 类成员必须用一行分隔。
BestIt.Spacing.ConstantSpacing.IncorrectCountOfBlankLinesAfterConstant 常量必须用一行分隔。
BestIt.Spacing.NamespaceSpacing.IncorrectLinesCountAfterNamespace 命名空间后必须有一行。
BestIt.Spacing.NamespaceSpacing.IncorrectLinesCountBeforeNamespace 命名空间前必须有一行。
BestIt.Spacing.PropertySpacing.IncorrectCountOfBlankLinesAfterProperty 属性后必须有一行。
BestIt.Spacing.SpaceAfterDeclare.GroupBlankLineFound 多个声明语句应该分组,无需空白行。
BestIt.Spacing.SpaceAfterDeclare.MuchWhitespaceFound 声明语句后必须只有一行。
BestIt.Spacing.SpaceAfterDeclare.NoWhitespaceFound 声明语句后必须有一行空行。
BestIt.Spacing.SpaceAroundConcat.MissingSpaceAroundConcat 您必须在concat-dot周围使用空格字符。
BestIt.Spacing.TraitUseSpacing.IncorrectLinesCountAfterLastUse 您必须在您的最后一个特质使用后不提供额外的行。
BestIt.Spacing.TraitUseSpacing.IncorrectLinesCountBeforeFirstUse 您必须在您的第一个特质使用前不提供额外的空白行。
BestIt.Spacing.TraitUseSpacing.IncorrectLinesCountBetweenUses 您必须在特质使用之间不提供额外的空白行。
BestIt.Spacing.UseSpacing.IncorrectLinesCountAfterLastUse 在最后一次使用后必须有一行。
BestIt.Spacing.UseSpacing.IncorrectLinesCountBeforeFirstUse 在第一次使用前必须有一行。
BestIt.Spacing.UseSpacing.IncorrectLinesCountBetweenDifferentTypeOfUse 不同使用之间不能有行。
BestIt.Spacing.UseSpacing.IncorrectLinesCountBetweenSameTypeOfUse 相同使用之间不能有行。
BestIt.Strings.ConcatCalculationSniff.CalculationWithoutBrackets 您必须用括号封装您的计算。
BestIt.TypeHints.ExplicitAssertions.RequiredExplicitAssertion 使用断言而不是内联文档注释。
BestIt.TypeHints.PropertyTypeHint.MissingAnyTypeHint 如果可能,必须有任何类型提示。
BestIt.TypeHints.PropertyTypeHint.MissingNativeTypeHint 必须有一个原生类型提示(与文档块匹配)。
BestIt.TypeHints.ReturnTypeDeclaration.MissingReturnTypeHint 每个函数或方法都必须有类型提示,如果返回注释有效。
BestIt.TypeHints.SuggestExplicitReturnType.MixedType 您不应该使用混合类型,而应该使用显式原生返回类型。
Generic.Formatting.SpaceAfterCast 类型转换后必须有一行空格。
Generic.Arrays.DisallowLongArraySyntax 每个数组语法都必须使用短数组语法。
SlevomatCodingStandard.Classes.ClassConstantVisibility.MissingConstantVisibility 常量必须带有可见性标记。
SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName 不能通过其FQCN使用任何类。您必须导入每个类!
SlevomatCodingStandard.TypeHints.DeclareStrictTypes 每个文件都必须在开标签后有两行断行符,并包含 "declare(strict_types=1);"。等号周围不能有空格。
Squiz.Strings.DoubleQuoteUsage 每个字符串必须用单引号包裹。

开发

简介

代码嗅探器基于一种基于标记的嗅探机制。

您可以使用代码嗅探器 cli 的 详细选项,查看在您的文件中哪些标记被解析以及它们在文件中的位置。请参考官方代码嗅探器教程了解编写自定义嗅探器的理论。

本教程的要点是,您需要实现 PHP_CodeSniffer\Sniffs\Sniff 接口,该接口强制执行两个方法

1. 标记注册

register 方法应返回您想要嗅探的标记的解析器标记 ID。

2. 处理

当调用 process 方法时,它将带有您注册的标记在给定文件对象的标记堆栈中的位置的参数。

最佳 IT "助手"

BestIt\Sniffs\AbstractSniff

我们将基本工作重构到这个抽象类中。您可以使用扩展的 API 获取更干净的 API,并跳过简单的样板代码。

  • areRequirementsMet:如果此方法返回 false,则嗅探器将被“跳过”。
  • isSniffSuppressed:如果此方法返回 true,则提供了抑制注释,并且嗅探器应该被“跳过”。
  • processToken:将正常 API 的样板代码保存在对象属性中,您可以在不“重新实现”基本接口及其方法参数的情况下嗅探您的标记。
  • setUp:您可以在使用 areRequirementsMet 检查要求之前设置测试。
  • tearDown:如果想要“销毁”此嗅探器,则可以在嗅探处理之后将其拆解。

CodeSniffer 的设计是无状态的,即使嗅探器类用作“单例”。因此,如果在嗅探器中保存状态,则必须在之后进行 tearDown 或在 setUp 中正确初始化。

BestIt\Sniffs\DocTags\AbstractTagSniff

这个抽象类可以帮助您嗅探单个文档标记。只需实现给定的抽象方法,您就可以注册并嗅探特定的文档标记,并检查其内容,直到换行符。

BestIt\Sniffs\DocTags\TagContentFormatTrait

这个特性旨在与 AbstractTagSniff 一起使用,并为您提供了一个 API,该 API 会自动将标记内容与正则表达式模式进行比较,如果出现错误或警告,则使用代码 TagContentFormatInvalid

BestIt\Sniffs*RegistrationTrait

我们提供了一些特性,这些特性使注册类似类的结构、常量、方法和属性的嗅探器变得更容易。

测试

要求

要能够测试我们编写的嗅探器,请确保 composer 已安装并带有 --prefer-source 选项。这是必需的,因为我们使用了 SlevomatCodingStandard 的 TestCase。

错误代码作为公共常量

除了可读性和干净的代码,我们的测试基础还要求你在嗅探类中提供错误代码作为公共常量,并以前缀 CODE_ 开头。

没有 "Test" 命名空间

我们的测试基础期望你在 "正常" 命名空间中提供一切: BestIt

帮助测试特性

令牌注册

特性 BestIt\Sniffs\TestTokenRegistrationTrait 帮助你测试已注册的令牌。

公共错误代码

特性 BestIt\Sniffs\TestRequiredConstantsTrait 帮助你测试错误代码。我们建议你也测试这些值,因为它们可能是来自你的 "客户" 的 "外部规则集" 的一部分,不受你的控制。因此,我们强制这些常量值保持 API 稳定性!

默认集成测试

特性 BestIt\Sniffs\DefaultSniffIntegrationTestTrait 提供了三个测试,用于测试基于嗅探器单独测试文件的通常用例。

  1. testCorrect
  2. testErrors
  3. testWarnings
要求
  • 你的测试文件应与你的嗅探器完全相同(包括命名空间),但后缀为 Test
  • 提供一个名为 Fixtures 的文件夹,作为你的测试文件的同级文件夹。
  • 在你的 "Fixtures" 目录中创建一个文件夹,其名称与嗅探器的简称完全相同。
testCorrect

在你的 fixtures 目录中创建一个名为 correct 的文件夹。该文件夹中的每个 PHP 文件都将与你的嗅探器进行检查。嗅探器可能不会为成功测试填充错误和警告!

testErrors

在你的 fixtures 目录中创建一个名为 with_errors 的文件夹。该文件夹中的每个 PHP 文件都应在你的嗅探器中触发错误。你必须通过文件名提供错误结构。文件名必须匹配以下 pregex

/(?P<code>[\w]+)(\(\w*\))?\.(?P<errorLines>[\d-\,]+)(?P<fixedSuffix>\.fixed)?\.php/

文件名提供了有关应发生哪些错误以及在哪一行的信息。示例文件可能是 ErrorCode.1.php, ErrorCode.1,2,3.php, ErrorCode.1,2,3.fixed.php,ErrorCode(2).1,2,3.php,ErrorCode(2).1,2,3.fixed.php_。错误代码必须是你的嗅探器的原始代码值,第一个点之后的所有数字是错误的行号。

如果你提供了一个以 "fixed" 结尾的附加文件,则这是其错误兄弟的正确格式化的文件。

testWarnings

在你的 fixtures 目录中创建一个名为 with_warnings 的文件夹。该文件夹中的每个 PHP 文件都应在你的嗅探器中触发警告。你必须通过文件名提供警告结构。文件名必须匹配以下 pregex

/(?P<code>[\w]+)(\(\w*\))?\.(?P<errorLines>[\d-\,]+)(?P<fixedSuffix>\.fixed)?\.php/

文件名提供了有关应发生哪些警告以及在哪一行的信息。示例文件可能是 WarningCode.1.php, WarningCode.1,2,3.php, WarningCode.1,2,3.fixed.php,WarningCode(2).1,2,3.php,WarningCode(2).1,2,3.fixed.php_。警告代码必须是你的嗅探器的原始代码值,第一个点之后的所有数字是带有警告的行号。

如果你提供了一个以 "fixed" 结尾的附加文件,则这是其错误兄弟的正确格式化的文件。

贡献

请参阅 CONTRIBUTING.md

语义版本化

我们使用与我们的规则集强制执行的样式相关的语义化版本控制,而不是直接与我们的源代码相关。这意味着,我们的代码中可能存在破坏性更改,但只要样式没有发生重大变化,破坏性更改就不会反映在我们的版本号中。

  • 补丁版本(最后一位数):规则集中的向后兼容的错误修复
  • 次要版本(中间位数):规则集中的向后兼容的新特性(仅警告、删除或可自动修复的错误)
  • 主版本(第一位数):规则集中的破坏性更改

我们优化版本控制是为了sniffer的使用,而不是为了开发!

待办事项

  • 删除内部API的进一步slevomat依赖。