orklah
Repos
42
Followers
44
Following
90

Adds strict_types declaration when the file is provably safe

13
0

Detects possible insane comparison ("string" == 0) to help migrate to PHP8

31
1

Automatically change empty() into a more explicit expression

24
1

Automatically change == into === when safe

5
1

Restrict the use of (int) and (float) to numeric-string only

5
1

A Psalm plugin to detect calling private or protected method via proxy

6
0

Events

issue comment
`TDependentListKey` in `MinMaxReturnTypeProvider`

Note that TDependentListKey has a min at 0 and a max at null (can't be negative) contrary to int

Created at 29 minutes ago
issue comment
conditional return incorrectly handles non-empty-mixed with false

Not sure this can be fixed easily.

If I remember correctly, conditional returns works as follow:

  • if the param is mixed, we take the union of the first and second operand
  • if the param is contained by the checked type, we take the first operand
  • otherwise we take the second operand

So, non-empty-mixed is considered mixed. I think this checks takes precedence over checking the second item from the list above.

Created at 20 hours ago
issue comment
add hideAllErrorsExceptPassedFiles config option

Thanks!

Created at 1 day ago

add hideAllErrorsExceptPassedFiles config option

for files only (not directories, since that wouldn't make practical sense)

add docs

Merge pull request #8502 from kkmuffme/option-to-only-report-errors-for-passed-file

add hideAllErrorsExceptPassedFiles config option

Created at 1 day ago
closed issue
Option to not report errors for required/included files

By default, psalm reports errors for files that were included in the current file if running pslam for 1 file: psalm foo.php

foo.php

echo 'foo';

require 'bar.php';

will also report errors for bar.php

When I specify just a single file, I expect that I only get errors from that 1 file. Is there an option to get this behavior?

Created at 1 day ago
pull request closed
add hideAllErrorsExceptPassedFiles config option

for files only (not directories, since that wouldn't make practical sense)

Fix: https://github.com/vimeo/psalm/issues/5322

Created at 1 day ago
issue comment
add hideAllErrorsExceptPassedFiles config option

You can put that in configuration.md so it ends up here: https://psalm.dev/docs/running_psalm/configuration/

Created at 3 days ago

fix crash in <PHP8 with ResourceBundle

partially reverts https://github.com/vimeo/psalm/pull/8217

add code for faster debugging next time

Merge pull request #8416 from kkmuffme/regression-4.25.0-count-resourcebundle

fix crash in <PHP8 with ResourceBundle

Created at 3 days ago
closed issue
4.25.0 Regression: Could not get class storage for resourcebundle for PHP < 8.0

When I run --alter: EDIT: seems to be there without --alter too

php /opt/composer/vendor/bin/psalm --config=my-rules.xml --alter --plugin=vendor/orklah/psalm-strict-equality/src/Plugin.php --php-version=7.4 my-file.php

When I do --php-version=8.0 or --php-version=8.1 I don't get an error. For everythint <= 7.4 I get this error.

Uncaught InvalidArgumentException: Could not get class storage for resourcebundle in /path/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php:46
Stack trace:
#0 /path/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeExpander.php(607): Psalm\Internal\Provider\ClassLikeStorageProvider->get('ResourceBundle')
#1 /path/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeExpander.php(178): Psalm\Internal\Type\TypeExpander::expandNamedObject(Object(Psalm\Codebase), Object(Psalm\Type\Atomic\TNamedObject), NULL, NULL, NULL, false, true)
#2 /path/vendor/vimeo/psalm/src/Psalm/Internal/Type/TypeExpander.php(82): Psalm\Internal\Type\TypeExpander::expandAtomic(Object(Psalm\Codebase), Object(Psalm\Type\Atomic\TNamedObject), NULL, NULL, NULL, true, false, false, true, false)
#3 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php(284): Psalm\Internal\Type\TypeExpander::expandUnion(Object(Psalm\Codebase), Object(Psalm\Type\Union), NULL, NULL, NULL, true, false, false, true)
#4 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php(195): Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::checkFunctionLikeTypeMatches(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(Psalm\Codebase), 'count', NULL, NULL, NULL, Object(Psalm\CodeLocation), Object(Psalm\Storage\FunctionLikeParameter), true, Object(Psalm\Type\Union), 0, 0, Object(PhpParser\Node\Arg), Object(Psalm\Context), Array, NULL, true, true)
#5 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php(828): Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentAnalyzer::checkArgumentMatches(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), 'count', NULL, NULL, NULL, Object(Psalm\CodeLocation), Object(Psalm\Storage\FunctionLikeParameter), 0, 0, true, Object(PhpParser\Node\Arg), Object(Psalm\Type\Union), Object(Psalm\Context), Array, NULL, true, true)
#6 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php(214): Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer::checkArgumentsMatch(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Array, 'count', Array, NULL, NULL, Object(Psalm\Internal\Type\TemplateResult), Object(Psalm\CodeLocation), Object(Psalm\Context))
#7 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(296): Psalm\Internal\Analyzer\Statements\Expression\Call\FunctionCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\FuncCall), Object(Psalm\Context))
#8 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(78): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\FuncCall), Object(Psalm\Context), false, NULL, false)
#9 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/BinaryOpAnalyzer.php(120): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\FuncCall), Object(Psalm\Context))
#10 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(266): Psalm\Internal\Analyzer\Statements\Expression\BinaryOpAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\BinaryOp\Identical), Object(Psalm\Context), 0, false)
#11 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(78): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\BinaryOp\Identical), Object(Psalm\Context), false, NULL, false)
#12 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfConditionalAnalyzer.php(117): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\BinaryOp\Identical), Object(Psalm\Context))
#13 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php(107): Psalm\Internal\Analyzer\Statements\Block\IfConditionalAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\BinaryOp\Identical), Object(Psalm\Context), Object(Psalm\Codebase), Object(Psalm\Internal\Scope\IfScope), 11411)
#14 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(518): Psalm\Internal\Analyzer\Statements\Block\IfElseAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context))
#15 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context), NULL)
#16 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php(68): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context))
#17 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php(365): Psalm\Internal\Analyzer\Statements\Block\IfElse\IfAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Internal\Scope\IfScope), Object(Psalm\Internal\Scope\IfConditionalScope), Object(Psalm\Context), Object(Psalm\Context), Object(Psalm\Context), Array)
#18 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(518): Psalm\Internal\Analyzer\Statements\Block\IfElseAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context))
#19 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context), Object(Psalm\Context))
#20 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(476): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#21 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php(96): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), Object(Psalm\Context))
#22 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(564): Psalm\Internal\Analyzer\FunctionAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Function_), Object(Psalm\Context))
#23 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Function_), Object(Psalm\Context), Object(Psalm\Context))
#24 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(205): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#25 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php(204): Psalm\Internal\Analyzer\FileAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Context))
#26 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(347): Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Include_), Object(Psalm\Context), Object(Psalm\Context))
#27 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(78): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Include_), Object(Psalm\Context), false, Object(Psalm\Context), true)
#28 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(572): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Include_), Object(Psalm\Context), false, Object(Psalm\Context), true)
#29 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Expression), Object(Psalm\Context), Object(Psalm\Context))
#30 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(476): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#31 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php(96): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), Object(Psalm\Context))
#32 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(564): Psalm\Internal\Analyzer\FunctionAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Function_), Object(Psalm\Context))
#33 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Function_), Object(Psalm\Context), NULL)
#34 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(205): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), NULL, true)
#35 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/IncludeAnalyzer.php(204): Psalm\Internal\Analyzer\FileAnalyzer->analyze(Object(Psalm\Context), NULL)
#36 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(347): Psalm\Internal\Analyzer\Statements\Expression\IncludeAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Include_), Object(Psalm\Context), NULL)
#37 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(78): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Include_), Object(Psalm\Context), false, NULL, true)
#38 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(572): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Include_), Object(Psalm\Context), false, NULL, true)
#39 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Expression), Object(Psalm\Context), NULL)
#40 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/ElseIfAnalyzer.php(274): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context))
#41 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php(390): Psalm\Internal\Analyzer\Statements\Block\IfElse\ElseIfAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\ElseIf_), Object(Psalm\Internal\Scope\IfScope), Object(Psalm\Context), Object(Psalm\Context), Object(Psalm\Codebase), 63749)
#42 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(518): Psalm\Internal\Analyzer\Statements\Block\IfElseAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context))
#43 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context), Object(Psalm\Context))
#44 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(476): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#45 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionAnalyzer.php(96): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), Object(Psalm\Context))
#46 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(564): Psalm\Internal\Analyzer\FunctionAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Function_), Object(Psalm\Context))
#47 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(207): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Function_), Object(Psalm\Context), NULL)
#48 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(205): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), NULL, true)
#49 /path/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(362): Psalm\Internal\Analyzer\FileAnalyzer->analyze()
#50 /path/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(619): Psalm\Internal\Codebase\Analyzer->Psalm\Internal\Codebase\{closure}(0, '/path/to/my-file...')
#51 /path/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(291): Psalm\Internal\Codebase\Analyzer->doAnalysis(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1)
#52 /path/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(1161): Psalm\Internal\Codebase\Analyzer->analyzeFiles(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1, true, false)
#53 /path/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalter.php(412): Psalm\Internal\Analyzer\ProjectAnalyzer->checkFile('/path/to/my-file...')
#54 /path/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(931): Psalm\Internal\Cli\Psalter::run(Array)
#55 /path/vendor/vimeo/psalm/src/Psalm/Internal/Cli/Psalm.php(177): Psalm\Internal\Cli\Psalm::forwardCliCall(Array, Array)
#56 /path/vendor/vimeo/psalm/psalm(6): Psalm\Internal\Cli\Psalm::run(Array)
#57 /path/vendor/bin/psalm(115): include('/path/v...')
#58 {main}
(Psalm v4.25.0@d7cd84c4ebca74ba3419b9601f81d177bcbe2aac crashed due to an uncaught Throwable)
Created at 3 days ago
pull request closed
fix crash in <PHP8 with ResourceBundle

Fix https://github.com/vimeo/psalm/issues/8346

partially reverts https://github.com/vimeo/psalm/pull/8217

Created at 3 days ago
issue comment
fix crash in <PHP8 with ResourceBundle

Thanks!

Created at 3 days ago
issue comment
Properly propagate clones

This will go on master and I'm waiting for the immutable PR to release the master branch so it won't come quicker anyway

Created at 3 days ago
issue comment
isset()/empty() does not generate issues for non-existing/non-declared attributes and variables

Note that the error is very much raised, as long as you're not in global scope: https://psalm.dev/r/bca86bf891

Basically, if you're in global scope, anything could be defined, we just have no idea.

Raising an error for each variable unknown in global scope would generate a massive number of unfixable false positives that would ruin the experience exactly on the projects that are most likely to use empty

I'm not sure if there's anything we can do here

Created at 3 days ago
issue comment
false positive with unpacked and named arguments

It's possibly a flaw in the improvement I made here: https://github.com/vimeo/psalm/pull/7348 or something very close

This is admittedly a pretty niche case, unpacking a sealed array then using a named parameter is a little weird, but as long as the array is sealed, it should be possible to adapt the code by both counting the elements in the array and deducting the named elements

Created at 3 days ago
issue comment
Optional before required function parameters not recognized

To be discussed: I'm not actually sure it should be the role of Psalm to report this.

It seems to me that code style rules are perfectly equipped to enforce this kind of things

Created at 3 days ago
closed issue
Feature: environments to allow some specific checks for CLI

https://psalm.dev/r/f8d4abb85a

Some variables are only accessible in CLI (e.g. $argv, $argc) as well as some things do only/not work in CLI, e.g. filter_input doesn't work in CLI with INPUT_SERVER (always empty),... By checking for environments a lot of those often "hidden" issues could be unearthed.

Created at 3 days ago
issue comment
Feature: environments to allow some specific checks for CLI

Merged :)

Created at 3 days ago
issue comment
PossiblyNullArgument: Adding common problem cases and possible solutions

I'm not actually sure... It may be that the pages are still built from 4.X but it seems strange... I'll keep this in my todo list to check when I have some free time

Created at 3 days ago
issue comment
PossiblyUndefinedIntArrayOffset wrong for list

The issue here is a possibly not precise enough refinement: https://psalm.dev/r/a71c257367

The isset turns the list<string> into a array{10: string}<int, string>

This is technically correct but it's not the best way to store the new type. Instead, it should become a non-empty-list<string> and have the hidden property TNonEmptyList::$count set to 11 (maybe check the off by one here).

Created at 3 days ago
issue comment
add hideAllErrorsExceptPassedFiles config option

I'd like to have some documentation on new configs please

Created at 3 days ago
issue comment
use cache for declared function when available before falling back to stubs

Thanks!

Created at 3 days ago
closed issue
InvalidReturnType are reported for stubs

I have a project where a function exists both in the stubs AND in the code to analyze (basically: overwriting a function/method, but also for cases where psalm is unable to infer/load files due to how paths are loaded)

In my file I have this (just a mock example): https://psalm.dev/r/e7f20deb65

Problem: as this function exists in my stubs too, Psalm now reports this error for the stubs file - which gets suppressed (since errors in stubs file paths are suppressed by psalm by default) Therefore this error never shows up.

Why this is a problem? Psalm always takes the phpdoc from the stubs as truth (this is fine/good). It then uses the code (not stubs) to check if the code matches the phpdoc. In this case however, it would make much more sense to report the error not for the stubs but for the file where it checks the code in.

I remember I had a similar issue a long time ago, when I got started with psalm, so I think this is not an isolated issue with InvalidReturnType

EDIT: this affects all (but only) PHPDoc issues for functions. While most of them get reported for both the stubs + the file the issue is in, InvalidReturnType and MissingParamType get only reported for the stubs. But e.g. InvalidDocblock is reported for both (stubs and the file)

Created at 3 days ago

use cache for declared function when available before falling back to stubs

fixes return type issues reported for the wrong file

Merge pull request #8503 from kkmuffme/fix-phpdoc-errors-reported-for-stubs-instead-of-files

use cache for declared function when available before falling back to stubs

Created at 3 days ago
pull request closed
use cache for declared function when available before falling back to stubs

fixes return type issues reported for the wrong file

Fix https://github.com/vimeo/psalm/issues/8457

Created at 3 days ago
issue comment
Does declare(strict_types=1) affect Psalm?

There is a slight but notable difference:

https://psalm.dev/r/484b28635d

That happens if you try to call an internal function on a mixed variable (full code here: https://github.com/vimeo/psalm/blob/8098755ce5ad6f3048506860fb9b90a1777c24a9/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php#L1137)

If you are in strict mode, Psalm will assume that the type of your variable is the type of the parameter of the method you just called (because otherwise, you would have gotten a TypeError). But it won't do that if you're not in strict mode.

Otherwise, I believe it just impacts the severity of the error raised

Created at 4 days ago
pull request closed
bump slevomat/coding-standard to fix CI

This will fix the CI crash

Created at 4 days ago
issue comment
bump slevomat/coding-standard to fix CI

outdated

Created at 4 days ago
issue comment
Allow `value-of` to work with backed enums (fixes #7874).

oh sorry, didn't check the target indeed.

We can release a beta if we want. I was hoping a final release in september after the immutable refactor but we may have to wait a bit more

Created at 5 days ago