glhd / laralint
Laravel 代码格式化框架
Requires
- php: >=7.3.0
- illuminate/console: ^6.0|^7.0|^8.0|^9.0|10.*|^11.0
- illuminate/support: ^6.0|^7.0|^8.0|^9.0|10.*|^11.0
- microsoft/tolerant-php-parser: dev-main
Requires (Dev)
- laravel/framework: ^6.0|^7.0|^8.0|^9.0|10.*|^11.0
- orchestra/testbench: ^4.0|^5.0|^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.0
README
这是一个 非常早期 的 Laravel 项目代码格式化工具。它与其他 PHP 格式化工具的不同之处在于,它专注于构建符合您特定需求的自定义规则。
目标是让 编写自定义格式化工具 变得简单流畅,就像编写 Laravel 后端代码一样。虽然该项目在底层使用了 AST/tokenizers 等技术,但对于大多数常见场景,您不需要深入了解其工作原理。
入门指南
使用以下命令将此工具安装到您的项目中:
composer require glhd/laralint --dev
安装完成后,您可以通过运行以下命令来使用 LaraLint 的默认规则对项目进行代码格式化:
php artisan laralint:lint
如果您只想格式化未提交的 Git 修改,可以将 --diff
参数传递给命令
php artisan laralint:lint --diff
或者,如果您只想格式化特定文件,可以将文件名作为第一个参数传递
php artisan laralint:lint app/Http/Controllers/HomeController.php
配置和预设
LaraLint 随带了一个 非常明确的 预设。如果您觉得这个预设适用,那很好,但您可能需要对其进行自定义,以符合您团队的代码标准。
首先,发布 LaraLint 配置文件:
php artisan vendor:publish --tag=laralint-config
这将安装一个 laralint.php
文件到您的项目 config/
目录中,并包含默认的 LaraLint 配置。
在某些情况下,您可能只需调整配置即可满足需求。但更有可能的是,您需要创建自己的预设。
请查看 Preset 合同或默认的 LaraLint 预设 以开始。从那里,您可以创建一个适用于项目的自定义预设,使用对团队有意义的 linters。尽情地混合和匹配预构建的 linters 和您自己的 自定义 linters 吧!
自定义 linters
如果您对 LaraLint 感兴趣,您可能也对自定义 linters 感兴趣。每个团队的需求都不同,LaraLint 尝试使快速添加强制执行您约定的约定的逻辑尽可能简单。
尽管如此,LaraLint 确实 依赖于像抽象语法树这样的概念,一开始可能会让人感到有些难以理解。但掌握一些关键概念后,您应该很快就能像高手一样遍历这个树了!
快速了解:LaraLint 的工作原理
用尽可能少的词语描述
LaraLint 使用 Microsoft 的 Tolerant PHP Parser 将您的 PHP 代码解析成抽象语法树(AST)。我们之所以使用 Microsoft 的解析器,是因为它速度快,能够很好地处理部分编写的代码(例如您在 IDE 中输入的代码)。它也是 VS Code 的 IntelliSense 的基础,因此有着良好的记录。
想象一下,这个树就是您代码的结构化视图。给定以下 PHP 代码
class Foo { public function bar() { return 'baz'; } }
AST 将看起来像这样(为了清晰起见进行了简化)
- ClassDeclaration (
class Foo
)- MethodDeclaration (
public function bar()
)- CompoundStatementNode (
return 'baz';
)- ReturnStatement (
return
)- StringLiteral (
'baz'
)
- StringLiteral (
- ReturnStatement (
- CompoundStatementNode (
- MethodDeclaration (
LaraLint 从上到下遍历这棵树,并将每个节点传递给每个适用的 Linter 进行检查。linters 是接收 AST 节点并可选地返回检查结果的简单对象。在完全遍历树之后,linters 才会返回检查结果。
这意味着您可以编写极其复杂和定制的代码检查工具,但希望您不需要这样做。
如何编写 LaraLint 代码检查工具
大多数 LaraLint 代码检查工具的核心是一个 Matcher
对象。这些对象被设计用来轻松地匹配一般的抽象语法树(AST)“形状”,并在找到整个“形状”时标记代码的一部分。例如,如果您想要标记任何名为 bar
的方法,该方法返回字符串 'baz'
,您可以使用以下匹配器
(new TreeMatcher()) // (1) Find a method declaration where the method name is "bar" ->withChild(function(MethodDeclaration $node) { return 'bar' === $node->getName(); }) // (2) Find any return statement ->withChild(ReturnStatement::class) // (3) Find a string literal that matches the string "baz" ->withChild(function(StringLiteral $node) { return 'baz' === $node->getStringContentsText(); }) ->onMatch(function(Collection $all_matched_nodes) { // Create a linting result using the matched nodes. // LaraLint will automatically map the AST nodes to line // numbers when printing the results. });
一旦 LaraLint 找到一个与第一个规则匹配的节点,它就会开始寻找一个与第二个规则匹配的子节点。如果它找到一个与第二个规则匹配的子节点,它就会移动到第三个规则。当它匹配所有规则时,匹配器将触发 onMatch
回调,您可以在其中执行任何您选择的附加逻辑。
LaraLint 随带了一些适用于常见用例的“策略”。这些策略抽象出更多的逻辑,是开始的最佳地点。查看一些现有的代码检查工具,以了解如何最好地使用每个策略。
但是等等…我该如何编写 LaraLint 代码检查工具呢?
好吧,您可能正在查看 ReturnStatement
和 StringLiteral
,并想,“我不会说抽象语法树。”
其他人也不会。
这就是 laralint:dump
命令发挥作用的地方。比如说,您正在尝试编写上面示例中的愚蠢的 bar/baz 代码检查工具。只需创建一个应该失败的 PHP 文件,并转储其树
php artisan laralint:dump barbaz_source.php
这将输出类似以下的内容
┏━━ ClassDeclaration ━━━━━━┓
┃ ┃
┃ class Foo ┃
┃ { ┃
┃ public function bar() ┃
┃ { ┃
┃ return 'baz'; ┃
┃ } ┃
┃ } ┃
┃ ┃
┃ ┏━━ ClassMembersNode ━━━━━━┓
┃ ┃ ┃
┃ ┃ { ┃
┃ ┃ public function bar() ┃
┃ ┃ { ┃
┃ ┃ return 'baz'; ┃
┃ ┃ } ┃
┃ ┃ } ┃
┃ ┃ ┃
┃ ┃ ┏━━ MethodDeclaration ━━━┓
┃ ┃ ┃ ┃
┃ ┃ ┃ public function bar() ┃
┃ ┃ ┃ { ┃
┃ ┃ ┃ return 'baz'; ┃
┃ ┃ ┃ } ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┏━━ CompoundStatementNode ━━┓
┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ { ┃
┃ ┃ ┃ ┃ return 'baz'; ┃
┃ ┃ ┃ ┃ } ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┏━━ ReturnStatement ━━┓
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ return 'baz'; ┃
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┏━━ StringLiteral ━━┓
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃ 'baz' ┃
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
在 dump
命令的输出和现有代码检查工具的示例之间,您会惊讶于开始编写自己的规则有多容易。
IDE 集成
代码检查结果的最佳位置就在您的 IDE 中。我们不需要发布自己的 IDE 插件,LaraLint 可以简单地假装是 PHP_CodeSniffer
php artisan laralint:lint --printer=phpcs
这将为您提供与任何可以解析 PHP_CodeSniffer
的 XML 输出的插件兼容的 XML 输出(如 PhpStorm)。
运行 php artisan laralint:install
将安装一个漂亮的辅助文件,这使得整个过程变得更容易。只需配置您的 IDE 以指向该文件,您的 LaraLint 代码检查应该会在 IDE 中被标记。