sirbrillig/phpcs-changed

对文件运行 phpcs,但只报告更改行的警告/错误。


README

在文件上运行 phpcs 并仅报告与上一版本相比的新警告/错误。

这是一个既可以手动使用也可以作为 CLI 脚本运行的 PHP 库。

这是用来做什么的?

假设你需要向一个包含许多 phpcs 错误的大型旧文件中添加功能。如果你尝试运行 phpcs,那么噪声太多,你几乎无法注意到你可能添加的任何错误。

使用此脚本,你可以获取仅适用于你已做的更改的 phpcs 输出,并忽略未更改的错误。

安装

composer global require sirbrillig/phpcs-changed

CLI 使用

👩‍💻👩‍💻👩‍💻

为了使此功能工作,你需要能够提供关于你的代码之前版本的资料。如果使用 svn 或 git,phpcs-changed 可以自行获取这些数据,或者你可以手动提供。

以下是一个使用 phpcs-changed--svn 选项的示例

phpcs-changed --svn file.php

如果你想手动使用 svn 和 phpcs,这将产生相同的输出

svn diff file.php > file.php.diff
svn cat file.php | phpcs --report=json -q > file.php.orig.phpcs
cat file.php | phpcs --report=json -q > file.php.phpcs
phpcs-changed --diff file.php.diff --phpcs-unmodified file.php.orig.phpcs --phpcs-modified file.php.phpcs

它们将输出类似的内容

FILE: file.php
-----------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
-----------------------------------------------------------------------------------------------
 76 | WARNING | Variable $foobar is undefined.
-----------------------------------------------------------------------------------------------

或者,使用 --report json

{
  "totals": {
    "errors": 0,
    "warnings": 1,
    "fixable": 0
  },
  "files": {
    "file.php": {
      "errors": 0,
      "warnings": 1,
      "messages": [
        {
          "line": 76,
          "message": "Variable $foobar is undefined.",
          "source": "VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable",
          "severity": 5,
          "fixable": false,
          "type": "WARNING",
          "column": 8
        }
      ]
    }
  }
}

如果文件由 git 版本控制,我们可以使用 --git 选项做同样的事情

phpcs-changed --git --git-unstaged file.php

在 使用 --git 时,你还应指定 --git-staged--git-unstaged--git-base

--git-staged 将当前已暂存的更改(作为文件的修改版本)与当前 HEAD(作为文件的未修改版本)进行比较。这是默认设置。

--git-unstaged 将当前(未暂存)的工作副本更改(作为文件的修改版本)与当前暂存的更改或如果没有,与当前 HEAD(作为文件的未修改版本)进行比较。

--git-base 后跟一个 git 对象,将当前 HEAD(作为文件的修改版本)与指定的 git 对象(作为文件的未修改版本)进行比较,该对象可以是分支名称、提交或其他有效的 git 对象。

git checkout add-new-feature
phpcs-changed --git --git-base master file.php

CLI 选项

可以在版本控制选项之后指定多个文件,包括全局和目录。如果有任何文件是目录,phpcs-changed 将扫描该目录中所有以 .php 结尾的文件并将它们处理。例如: phpcs-changed --git src/lib test/**/*.php 将在 src/lib/test/ 目录中的所有 php 文件上操作。

您可以使用 --ignore 忽略任何目录、文件或与提供的模式匹配的路径。例如: --ignore=bin/*,vendor/* 将忽略 bin 目录中的任何文件,以及 vendor。

您可以使用 --report 来自定义输出类型。 full(默认)是可读的,json 打印一个 JSON 对象,如上所示,而 'xml' 可用于 IDE。这些与同名 phpcs 报告器匹配。

您可以使用 --standard 来指定要运行的特定 phpcs 标准。这与同名的 phpcs 选项匹配。

您可以使用 --extensions 来指定 phpcs 应检查的有效文件扩展名列表。这些应该由逗号分隔。这与同名的 phpcs 选项匹配。

您还可以使用-s选项来在完整的报告中始终显示错误后的嗅探代码。这与同名phpcs选项匹配。

可以使用--error-severity--warning-severity选项来指示phpcs命令报告什么错误和警告严重性。这些值将被传递给phpcs本身。请参阅phpcs文档了解严重性设置。

--cache选项将启用缓存phpcs输出,可以显著提高缓慢的phpcs标准或频繁运行时的性能。实际上有两个缓存:一个用于未修改版本的文件的phpcs扫描,一个用于修改版本的phpcs扫描。当版本控制修订更改或phpcs标准更改时,未修改版本phpcs输出缓存将失效。当文件哈希更改或phpcs标准更改时,修改版本phpcs输出缓存将失效。

--no-cache选项将禁用已启用的缓存。(这将来也可能有用,如果缓存成为默认设置。)

--clear-cache选项将在运行前清除缓存。此选项适用于启用或禁用缓存。

--always-exit-zero选项将确保运行始终以0返回代码退出,无论是否存在lint问题。未设置时,如果存在一些lint问题,则返回1,如果没有发现lint问题,则返回0。该标志使得phpcs-changed可以与其他检测脚本运行失败的标志(例如:arcanist)一起工作。

--no-verify-git-file选项将阻止在git工作流程中检查文件是否被git跟踪。如果您可以保证这一点,这可以节省一些时间。

--no-cache-git-root选项将阻止在单次执行中缓存git工作流程用于确定git根目录的检查。这可能仅适用于自动化测试。

--arc-lint选项可以在通过arcanist运行phpcs-changed时使用,因为它跳过了arcanist本身执行的一些检查。与arcanist一起使用时,可以提高性能。(相当于--no-verify-git-file --always-exit-zero。)

--svn-path--git-path--cat-path--phpcs-path选项可用于指定同名可执行文件的路径。如果没有设置这些选项,程序将尝试使用SVNGITCATPHPCS环境变量。如果没有设置这些环境变量,程序将默认使用svngitcatphpcs,假设每个命令都位于系统的PATH中。

对于phpcs,如果未覆盖路径,并且此命令运行的vendor/bin目录下存在phpcs可执行文件,则将使用该可执行文件而不是依赖于PATH。您可以使用--no-vendor-phpcs选项禁用此功能。

--debug选项将显示脚本执行的每一步。

PHP库

🐘🐘🐘

getNewPhpcsMessagesFromFiles

此库公开了一个函数PhpcsMessages\getNewPhpcsMessagesFromFiles(),它接受三个参数

  • 包含单个文件完整统一差异的文件路径。
  • 包含在您的最近更改之前对文件运行phpcs产生的消息的文件路径。
  • 包含在您的最近更改之后对文件运行phpcs产生的消息的文件路径。

它将返回一个PhpcsMessages实例,这是上述第三个参数的过滤列表,其中已经删除了第二个参数中的每一行。

PhpcsMessages代表运行phpcs的输出。

要读取PhpcsMessages实例的phpcs JSON输出,可以使用toPhpcsJson()方法。例如

use function PhpcsChanged\getNewPhpcsMessagesFromFiles;

$changedMessages = getNewPhpcsMessagesFromFiles(
	$unifiedDiffFileName,
	$oldFilePhpcsOutputFileName,
	$newFilePhpcsOutputFileName
);

echo $changedMessages->toPhpcsJson();

这将输出类似的内容

{
  "totals": {
    "errors": 0,
    "warnings": 1,
    "fixable": 0
  },
  "files": {
    "file.php": {
      "errors": 0,
      "warnings": 1,
      "messages": [
        {
          "line": 20,
          "type": "WARNING",
          "severity": 5,
          "fixable": false,
          "column": 5,
          "source": "ImportDetection.Imports.RequireImports.Import",
          "message": "Found unused symbol Foobar."
        }
      ]
    }
  }
}

getNewPhpcsMessages

如果前面的功能不够充分,此库公开了一个更底层的函数 PhpcsMessages\getNewPhpcsMessages(),它接受三个参数

  • (字符串) 单个文件的完整统一差异。
  • (PhpcsMessages) 在您最近的更改之前运行 phpcs 在文件上生成的消息。
  • (PhpcsMessages) 在您最近的更改之后运行 phpcs 在文件上生成的消息。

它将返回一个PhpcsMessages实例,这是上述第三个参数的过滤列表,其中已经删除了第二个参数中的每一行。

您可以使用 PhpcsMessages::fromPhpcsJson() 从实际的 phpcs JSON 输出创建一个 PhpcsMessages 实例。以下示例生成与上一个相同的输出

use function PhpcsChanged\getNewPhpcsMessages;
use function PhpcsChanged\getNewPhpcsMessagesFromFiles;
use PhpcsChanged\PhpcsMessages;

$changedMessages = getNewPhpcsMessagesFromFiles(
     $unifiedDiffFileName,
     $oldFilePhpcsOutputFileName,
     $newFilePhpcsOutputFileName
);

echo $changedMessages->toPhpcsJson();

多个文件

您可以使用 PhpcsChanged\PhpcsMessages::merge()getNewPhpcsMessagesgetNewPhpcsMessagesFromFiles 的结果组合起来,该函数接受一个 PhpcsMessages 实例数组并将它们合并到一个实例中。例如

use function PhpcsChanged\getNewPhpcsMessages;
use function PhpcsChanged\getNewPhpcsMessagesFromFiles;
use PhpcsChanged\PhpcsMessages;

$changedMessagesA = getNewPhpcsMessages(
     $unifiedDiffA,
     PhpcsMessages::fromPhpcsJson($oldFilePhpcsOutputA),
     PhpcsMessages::fromPhpcsJson($newFilePhpcsOutputA)
$changedMessagesB = getNewPhpcsMessagesFromFiles(
     $unifiedDiffFileNameB,
     $oldFilePhpcsOutputFileNameB,
     $newFilePhpcsOutputFileNameB
);

$changedMessages = PhpcsMessages::merge([$changedMessagesA, $changedMessagesB]);

echo $changedMessages->toPhpcsJson();

运行测试

在此目录中运行以下命令以运行内置测试套件

composer install
composer test

您还可以运行代码检查和静态分析

composer lint
composer static-analysis

调试

如果某些操作不符合您的预期,请使用 --debug 选项。这将显示大量输出。请特别注意脚本运行的 CLI 命令。您可以手动运行这些命令以更好地理解问题。

灵感

这受到了在 https://github.com/Automattic/phpcs-diff》上进行的令人惊叹的工作的启发