php质量工具系列之paslm

Psalm是一个静态分析工具,深入程序,尽可能多地找到与类型相关的bug

混合类型警告

Intelligent logic checks

属性初始化检查

Taint analysis

Language Server

Automatic fixes

Automatic refactoring

安装

shell 复制代码
composer global require --dev vimeo/psalm 
# 当使用这个方式安装时,如果psalm的依赖和项目依赖有冲突,可使用phar安装
composer global require --dev psalm/phar

注意:
linux 上,需要将全局composer的可执行目录加入环境变量,目录路径一般是/tmp/composer/vendor/bin
环境变量配置

windows 上,只需在环境变量path中加上composer路径,目录路径一般是

%APPDATA%\Composer\vendor\bin

初始化

shell 复制代码
./vendor/bin/psalm --init

psalm扫描你的项目,评估适合项目的错误级别,并生成psalm.xml文件用于后续的扫描配置

执行

shell 复制代码
./vendor/bin/psalm

#或者扫描某个或某些文件
./vendor/bin/psalm file1.php [file2.php...]
shell 复制代码
./vendor/bin/psalm --show-info=true

参数解释:

--show-info 显示非异常的分析结果

shell 复制代码
#针对特定问题给出psalm的解决方案,可参考其结果进行代码修复
./vendor/bin/psalm --alter --issues=MissingReturnType --dry-run

参数解释:

--issues all 显示全部问题解决方案;其他问题type,多个间以逗号分隔,如 MissingReturnType,InvalidArgument

插件

查看可用插件列表

shell 复制代码
composer search -t psalm-plugin '.'

安装

shell 复制代码
composer global require --dev <plugin-vendor/plugin-package>

启用

shell 复制代码
vendor/bin/psalm-plugin enable plugin-vendor/plugin-package

禁用

shell 复制代码
vendor/bin/psalm-plugin disable plugin-vendor/plugin-package

显示已安装列表

shell 复制代码
vendor/bin/psalm-plugin show

配置

以下是我的配置,大家可以根据情况选择配置

yaml 复制代码
<?xml version="1.0"?>
<psalm
    errorLevel="4"
    resolveFromConfigFile="true"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://getpsalm.org/schema/config"
    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
    findUnusedBaselineEntry="true"
    findUnusedCode="true"
    autoloader="psalm_autoloader.php"
    allowStringToStandInForClass="true"
>
    <!-- 添加错误忽略配置 -->
    <issueHandlers>
        <DocblockTypeContradiction>
            <errorLevel type="suppress">
                <directory name="app"/>
                <!--<file name="path/to/file_with_unused_methods.php"/>-->
            </errorLevel>
        </DocblockTypeContradiction>
        <NonInvariantDocblockPropertyType>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </NonInvariantDocblockPropertyType>
        <PossiblyUndefinedArrayOffset>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </PossiblyUndefinedArrayOffset>
        <PossiblyInvalidOperand>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </PossiblyInvalidOperand>
        <PossiblyUndefinedVariable>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </PossiblyUndefinedVariable>
        <RiskyTruthyFalsyComparison>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </RiskyTruthyFalsyComparison>
        <PossiblyInvalidMethodCall>
            <errorLevel type="suppress">
                <directory name="app/model"/>
            </errorLevel>
        </PossiblyInvalidMethodCall>
        <MissingReturnType>
            <errorLevel type="suppress">
                <directory name="app/model"/>
            </errorLevel>
        </MissingReturnType>
        <PossiblyNullOperand>
            <errorLevel type="suppress">
                <directory name="app/model"/>
            </errorLevel>
        </PossiblyNullOperand>
        <PossiblyNullArgument>
            <errorLevel type="suppress">
                <directory name="app/model"/>
            </errorLevel>
        </PossiblyNullArgument>
        <PropertyNotSetInConstructor>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </PropertyNotSetInConstructor>
        <UnusedClass>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </UnusedClass>
        <PossiblyUnusedMethod>
            <errorLevel type="suppress">
                <directory name="app"/>
            </errorLevel>
        </PossiblyUnusedMethod>
        <UndefinedConstant>
            <errorLevel type="suppress">
                <directory name="app"/>
                <directory name="config"/>
            </errorLevel>
        </UndefinedConstant>
        <UnusedConstructor>
            <errorLevel type="suppress">
                <file name="app/redis"/>
            </errorLevel>
        </UnusedConstructor>
        <UnusedMethod>
            <errorLevel type="suppress">
                <file name="app/common"/>
            </errorLevel>
        </UnusedMethod>
        <UnusedFunctionCall>
            <errorLevel type="suppress">
                <file name="app/common.php"/>
            </errorLevel>
        </UnusedFunctionCall>
        <PossiblyUnusedProperty>
            <errorLevel type="suppress">
                <file name="app/BaseController.php"/>
            </errorLevel>
        </PossiblyUnusedProperty>
        <InvalidArrayOffset>
            <errorLevel type="suppress">
                <file name="app/common.php"/>
            </errorLevel>
        </InvalidArrayOffset>
        <InvalidArgument>
            <errorLevel type="suppress">
                <file name="config/database.php"/>
            </errorLevel>
        </InvalidArgument>
    </issueHandlers>

    <!-- 配置需要扫描的范围,以及需要忽略的目录和文件 -->
    <projectFiles>
        <directory name="app" />
        <directory name="config" />
        <ignoreFiles>
            <directory name="vendor" />
            <directory name="test" />
            <file name="app/command/Swagger.php" />
        </ignoreFiles>
    </projectFiles>
</psalm>

文档解释:

issueHandlers 中是扫描问题的类型,其中directory 是需要忽略问题的目录,file是需要忽略问题的文件

自动化构建(Jenkins)中使用

参考文章 jenkins插件之Warnings 项目配置 一章中的psalm章节

相关推荐
石山岭10 小时前
自己动手写了一个 Android 虚拟定位 App:GPSSimulate 技术实
android·前端
杉氧12 小时前
副作用 (Side Effects) 全攻略:如何像大师一样掌控 Composable 的生命周期?
android·架构·android jetpack
Kapaseker16 小时前
Kotlin Toolchain 0.11 发布:主要是把 Amper 干没了
android·kotlin
三少爷的鞋17 小时前
Android 现代架构不需要事件总线进阶篇
android
杉氧1 天前
深入理解 Compose 重组机制:快照系统如何驱动 UI 精准刷新?
android·架构·android jetpack
召钱熏1 天前
状态枚举正确≠渲染正确:一个语音按钮的状态机边界修复实录
android·前端
杉氧1 天前
深度解析:Jetpack Compose 核心架构与底层原理 —— 十年安卓老兵的“破茧重生”
android·架构·android jetpack
通玄1 天前
Jetpack Compose 入门系列(七):ViewModel 与界面状态管理
android
落魄Android在线炒饭1 天前
Android Framework 开发技巧:android.jar 生成与系统快速编译验证
android
如此风景1 天前
Kotlin Flow操作符学习
android·kotlin