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章节

相关推荐
用户2018792831677 小时前
Android黑夜白天模式切换原理分析
android
芦半山7 小时前
「幽灵调用」背后的真相:一个隐藏多年的Android原生Bug
android
卡尔特斯8 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
ace望世界8 小时前
安卓的ViewModel
android
ace望世界8 小时前
kotlin的委托
android
CYRUS_STUDIO10 小时前
一文搞懂 Frida Stalker:对抗 OLLVM 的算法还原利器
android·逆向·llvm
zcychong10 小时前
ArrayMap、SparseArray和HashMap有什么区别?该如何选择?
android·面试
CYRUS_STUDIO11 小时前
Frida Stalker Trace 实战:指令级跟踪与寄存器变化监控全解析
android·逆向
ace望世界16 小时前
android的Parcelable
android
顾林海16 小时前
Android编译插桩之AspectJ:让代码像特工一样悄悄干活
android·面试·性能优化