psalm
psalm documentation
- Version in MegaLinter: Psalm.4.x-dev@
- Visit Official Web Site
- See How to configure psalm rules
- If custom
psalm.xml
config file is not found, psalm.xml will be used
- If custom
- See How to disable psalm rules in files
- See Index of problems detected by psalm
Configuration in MegaLinter
- Enable psalm by adding
PHP_PSALM
in ENABLE_LINTERS variable - Disable psalm by adding
PHP_PSALM
in DISABLE_LINTERS variable
Variable | Description | Default value |
---|---|---|
PHP_PSALM_ARGUMENTS | User custom arguments to add in linter CLI call Ex: -s --foo "bar" |
|
PHP_PSALM_FILTER_REGEX_INCLUDE | Custom regex including filter Ex: (src\|lib) |
Include every file |
PHP_PSALM_FILTER_REGEX_EXCLUDE | Custom regex excluding filter Ex: (test\|examples) |
Exclude no file |
PHP_PSALM_CLI_LINT_MODE | Override default CLI lint mode - file : Calls the linter for each file- list_of_files : Call the linter with the list of files as argument- project : Call the linter from the root of the project |
{linter.cli_lint_mode} |
PHP_PSALM_FILE_EXTENSIONS | Allowed file extensions. "*" matches any extension, "" matches empty extension. Empty list excludes all filesEx: [".py", ""] |
[".php"] |
PHP_PSALM_FILE_NAMES_REGEX | File name regex filters. Regular expression list for filtering files by their base names using regex full match. Empty list includes all files Ex: ["Dockerfile(-.+)?", "Jenkinsfile"] |
Include every file |
PHP_PSALM_PRE_COMMANDS | List of bash commands to run before the linter | None |
PHP_PSALM_POST_COMMANDS | List of bash commands to run after the linter | None |
PHP_PSALM_CONFIG_FILE | psalm configuration file nameUse LINTER_DEFAULT to let the linter find it |
psalm.xml |
PHP_PSALM_RULES_PATH | Path where to find linter configuration file | Workspace folder, then MegaLinter default rules |
PHP_PSALM_DISABLE_ERRORS | Run linter but consider errors as warnings | false |
PHP_PSALM_DISABLE_ERRORS_IF_LESS_THAN | Maximum number of errors allowed | 0 |
IDE Integration
Use psalm in your favorite IDE to catch errors before MegaLinter !
IDE | Extension Name | Install | |
---|---|---|---|
IDEA | PHPStan / Psalm / Generics | ||
Visual Studio Code | Psalm VsCode Plugin |
MegaLinter Flavours
This linter is available in the following flavours
Flavor | Description | Embedded linters | Info | |
---|---|---|---|---|
all | Default MegaLinter Flavor | 95 | ||
php | Optimized for PHP based projects | 44 |
Behind the scenes
How are identified applicable files
- File extensions:
.php
How the linting is performed
- psalm is called once with the list of files as arguments
Example calls
psalm myfile.php
psalm myfile.php mydir/
psalm --config=psalm.xml myfile.php
psalm --config=psalm.xml myfile.php mydir/
Help content
Usage:
psalm [options] [file...]
Basic configuration:
-c, --config=psalm.xml
Path to a psalm.xml configuration file. Run psalm --init to create one.
--use-ini-defaults
Use PHP-provided ini defaults for memory and error display
--memory-limit=LIMIT
Use a specific memory limit. Cannot be combined with --use-ini-defaults
--disable-extension=[extension]
Used to disable certain extensions while Psalm is running.
--threads=INT
If greater than one, Psalm will run analysis on multiple threads, speeding things up.
--no-diff
Turns off Psalm’s diff mode, checks all files regardless of whether they’ve changed.
Surfacing issues:
--show-info[=BOOLEAN]
Show non-exception parser findings (defaults to false).
--show-snippet[=true]
Show code snippets with errors. Options are 'true' or 'false'
--find-dead-code[=auto]
--find-unused-code[=auto]
Look for unused code. Options are 'auto' or 'always'. If no value is specified, default is 'auto'
--find-unused-psalm-suppress
Finds all @psalm-suppress annotations that aren’t used
--find-references-to=[class|method|property]
Searches the codebase for references to the given fully-qualified class or method,
where method is in the format class::methodName
--no-suggestions
Hide suggestions
--taint-analysis
Run Psalm in taint analysis mode – see https://psalm.dev/docs/security_analysis for more info
--dump-taint-graph=OUTPUT_PATH
Output the taint graph using the DOT language – requires --taint-analysis
Issue baselines:
--set-baseline=PATH
Save all current error level issues to a file, to mark them as info in subsequent runs
Add --include-php-versions to also include a list of PHP extension versions
--use-baseline=PATH
Allows you to use a baseline other than the default baseline provided in your config
--ignore-baseline
Ignore the error baseline
--update-baseline
Update the baseline by removing fixed issues. This will not add new issues to the baseline
Add --include-php-versions to also include a list of PHP extension versions
Plugins:
--plugin=PATH
Executes a plugin, an alternative to using the Psalm config
Output:
-m, --monochrome
Enable monochrome output
--output-format=console
Changes the output format.
Available formats: compact, console, text, emacs, json, pylint, xml, checkstyle, junit, sonarqube, github,
phpstorm, codeclimate
--no-progress
Disable the progress indicator
--long-progress
Use a progress indicator suitable for Continuous Integration logs
--stats
Shows a breakdown of Psalm’s ability to infer types in the codebase
Reports:
--report=PATH
The path where to output report file. The output format is based on the file extension.
(Currently supported formats: ".json", ".xml", ".txt", ".emacs", ".pylint", ".console",
".sarif", "checkstyle.xml", "sonarqube.json", "codeclimate.json", "summary.json", "junit.xml")
--report-show-info[=BOOLEAN]
Whether the report should include non-errors in its output (defaults to true)
Caching:
--clear-cache
Clears all cache files that Psalm uses for this specific project
--clear-global-cache
Clears all cache files that Psalm uses for all projects
--no-cache
Runs Psalm without using cache
--no-reflection-cache
Runs Psalm without using cached representations of unchanged classes and files.
Useful if you want the afterClassLikeVisit plugin hook to run every time you visit a file.
--no-file-cache
Runs Psalm without using caching every single file for later diffing.
This reduces the space Psalm uses on disk and file I/O.
Miscellaneous:
-h, --help
Display this help message
-v, --version
Display the Psalm version
-i, --init [source_dir=src] [level=3]
Create a psalm config file in the current directory that points to [source_dir]
at the required level, from 1, most strict, to 8, most permissive.
--debug
Debug information
--debug-by-line
Debug information on a line-by-line level
--debug-emitted-issues
Print a php backtrace to stderr when emitting issues.
-r, --root
If running Psalm globally you’ll need to specify a project root. Defaults to cwd
--generate-json-map=PATH
Generate a map of node references and types in JSON format, saved to the given path.
--generate-stubs=PATH
Generate stubs for the project and dump the file in the given path
--shepherd[=host]
Send data to Shepherd, Psalm’s GitHub integration tool.
--alter
Run Psalter
--language-server
Run Psalm Language Server
Installation on mega-linter Docker image
- Dockerfile commands :
# Parent descriptor install
RUN wget --tries=5 -q -O phive.phar https://phar.io/releases/phive.phar \
&& wget --tries=5 -q -O phive.phar.asc https://phar.io/releases/phive.phar.asc \
&& PHAR_KEY_ID="0x9D8A98B29B2D5D79" \
&& ( gpg --keyserver keyserver.pgp.com --recv-keys "$PHAR_KEY_ID" \
|| gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$PHAR_KEY_ID" \
|| gpg --keyserver pgp.mit.edu --recv-keys "$PHAR_KEY_ID" \
|| gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys "$PHAR_KEY_ID" ) \
&& gpg --verify phive.phar.asc phive.phar \
&& chmod +x phive.phar \
&& mv phive.phar /usr/local/bin/phive \
&& rm phive.phar.asc
# Linter install
RUN phive --no-progress install psalm -g --trust-gpg-keys 8A03EA3B385DBAA1,12CE0F1D262429A5
Example success log
Results of psalm linter (version 4.3.1)
See documentation on https://megalinter.github.io/descriptors/php_psalm/
-----------------------------------------------
[SUCCESS] .automation/test/php/php_good_1.php
Scanning files...
Analyzing files...
â–‘
------------------------------
No errors found!
------------------------------
Checks took 0.25 seconds and used 39.379MB of memory
Psalm was unable to infer types in the codebase
[SUCCESS] .automation/test/php/php_good_2.php
Scanning files...
Analyzing files...
â–‘
------------------------------
No errors found!
------------------------------
Checks took 0.31 seconds and used 36.996MB of memory
Psalm was unable to infer types in the codebase
Example error log
Results of psalm linter (version 4.3.1)
See documentation on https://megalinter.github.io/descriptors/php_psalm/
-----------------------------------------------
[ERROR] .automation/test/php/php_bad_1.php
Scanning files...
Analyzing files...
E
ERROR: ParseError - ../../...automation/test/php/php_bad_1.php:3:2 - Syntax error, unexpected T_STRING on line 3 (see https://psalm.dev/173)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:2 - Const pe98y is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:8 - Const r is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:10 - Const n0u823n is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: ParseError - ../../...automation/test/php/php_bad_1.php:3:17 - Syntax error, unexpected '=' on line 3 (see https://psalm.dev/173)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:18 - Const r is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: ParseError - ../../...automation/test/php/php_bad_1.php:3:21 - Invalid numeric literal on line 3 (see https://psalm.dev/173)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:24 - Const u3 is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:28 - Const r08u2q098ry is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: ParseError - ../../...automation/test/php/php_bad_1.php:3:40 - Syntax error, unexpected T_LNUMBER on line 3 (see https://psalm.dev/173)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:42 - Const nq2yr09n2yr9 is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:55 - Const y2n is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: ParseError - ../../...automation/test/php/php_bad_1.php:3:61 - Syntax error, unexpected T_STRING on line 3 (see https://psalm.dev/173)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:61 - Const yr is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
ERROR: UndefinedConstant - ../../...automation/test/php/php_bad_1.php:3:68 - Const yr3 is not defined (see https://psalm.dev/020)
2pe98y r-n0u823n=r 092u3- r08u2q098ry 09nq2yr09n2yr9 y2n-93yr 298yr3 29
------------------------------
15 errors found
------------------------------
Checks took 0.30 seconds and used 39.560MB of memory
Psalm was unable to infer types in the codebase
[ERROR] .automation/test/php/php_bad_2.php
Scanning files...
Analyzing files...
E
ERROR: InvalidReturnType - ../../...automation/test/php/php_bad_2.php:4:12 - The declared return type 'array<array-key, string>' for takesAnInt is incorrect, got 'array{int, string(hello)}' (see https://psalm.dev/011)
* @return array<string>
ERROR: InvalidReturnStatement - ../../...automation/test/php/php_bad_2.php:7:12 - The inferred type 'array{int, string(hello)}' does not match the declared return type 'array<array-key, string>' for takesAnInt (see https://psalm.dev/128)
return [$i, "hello"];
ERROR: InvalidScalarArgument - ../../...automation/test/php/php_bad_2.php:11:12 - Argument 1 of takesAnInt expects int, string(some text) provided (see https://psalm.dev/012)
takesAnInt($data[0]);
ERROR: ParseError - ../../...automation/test/php/php_bad_2.php:15:1 - Syntax error, unexpected '}' on line 15 (see https://psalm.dev/173)
} elseif ($condition) {}
------------------------------
4 errors found
------------------------------
Psalm can automatically fix 1 of these issues.
Run Psalm again with
--alter --issues=InvalidReturnType --dry-run
to see what it can fix.
------------------------------
Checks took 0.32 seconds and used 36.047MB of memory
Psalm was unable to infer types in the codebase