1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00
psalm/docs/issues.md
2018-01-07 17:25:23 -05:00

26 KiB
Raw Blame History

Issue types

AbstractInstantiation

Emitted when an attempt is made to instatiate an abstract class:

abstract class A {}
new A();

AssignmentToVoid

Emitted when assigning from a function that returns void:

function foo() : void {}
$a = foo();

CircularReference

Emitted when a class references itself as one of its parents

class A extends B {}
class B extends A {}

ContinueOutsideLoop

Emitted when encountering a continue statement outside a loop context.

DeprecatedClass

Emitted when creating a new instance of a deprecated class:

/** @deprecated */
class A {}
new A();

DeprecatedMethod

Emitted when calling a deprecated method on a given class:

class A {
    /** @deprecated */
    public function foo() : void {}
}
(new A())->foo();

DeprecatedProperty

Emitted when getting/setting a deprecated property of a given class

class A {
    /**
     * @deprecated
     * @var ?string
     */
    public $foo;
}
(new A())->foo = 5;

DuplicateClass

Emitted when a class is defined twice

class A {}
class A {}

DuplicateParam

Emitted when a class param is defined twice

class A {
    /** @var ?string */
    public $foo;
    /** @var ?string */
    public $foo;
}

EmptyArrayAccess

Emitted when attempting to access a value on an empty array

$a = [];
$b = $a[0];

FalsableReturnStatement

Emitted if a return statement contains a false value, but the function return type does not allow false

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return false; // emitted here
}

ForbiddenCode

Emitted when Psalm encounters a var_dump, exec or similar expression that may make your code more vulnerable

var_dump($foo);

ImplementedReturnTypeMismatch

Emitted when a class that inherits another, or implements an interface, has docblock return type that's entirely different to the parent. Subclasses of the parent return type are permitted, in docblocks.

class A {
    /** @return bool */
    public function foo() {
        return true;
    }
}
class B extends A {
    /** @return string */
    public function foo()  {
        return "hello";
    }
}

ImplicitToStringCast

Emitted when implictly converting an object with a __toString method to a string

class A {
    public function __toString() {
        return "foo";
    }
}

function takesString(string $s) : void {}

takesString(new A);

InaccessibleClassConstant

Emitted when a public/private class constant is not accessible from the calling context

class A {
    protected const FOO = 'FOO';
}
echo A::FOO;

InaccessibleMethod

Emitted when attempting to access a protected/private method from outside its available scope

class A {
    protected function foo() : void {}
}
echo (new A)->foo();

InaccessibleProperty

Emitted when attempting to access a protected/private property from outside its available scope

class A {
    /** @return string */
    protected $foo;
}
echo (new A)->foo;

InvalidArgument

Emitted when a supplied function/method argument is incompatible with the method signature or docblock one.

class A {}
function foo(A $a) : void {}
foo("hello");

InvalidArrayAccess

Emitted when attempting to access an array offset on a value that does not permit it

$arr = 5;
echo $arr[0];

InvalidArrayAssignment

Emitted when attempting to assign a value on a non-array

$arr = 5;
$arr[0] = 3;

InvalidArrayOffset

Emitted when when attempting to access an array using a value that's not a valid offet for that array

$a = [5, 20, 18];
echo $a["hello"];

InvalidCast

Emitted when attempting to cast a value that's not castable

class A {}
$a = new A();
$b = (string)$a;

InvalidCatch

Emitted when trying to catch a class/interface that doesn't extend Exception or implement Throwable

class A {}
try {
    $worked = true;
}
catch (A $e) {}

InvalidClass

Emitted when referencing a class with the wrong casing

class Foo {}
(new foo());

InvalidClone

Emitted when trying to clone a value that's not cloneable

$a = "hello";
$b = clone $a;

InvalidDocblock

Emitted when there's an error in a docblock type

/** @var array() */
$a = [];

InvalidFalsableReturnType

Emitted when a function can return a nullable value, but its given return type says otherwise

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return false;
}

InvalidFunctionCall

Emitted when calling a function on a non-callable variable

$a = 5;
$b = $a();

InvalidGlobal

Emitted when there's a reference to the global keyword where it's not expected

global $e;

InvalidIterator

Emitted when trying to iterate over a value that's not iterable

$a = 5;
foreach ($a as $b) {}

InvalidMethodCall

Emitted when attempting to call a method on a non-object

$a = 5;
$a->foo();

InvalidNullableReturnType

Emitted when a function can return a nullable value, but its given return type says otherwise

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return null;
}

InvalidOperand

Emitted when using something as an operand that is unexected

class A {}
echo (new A) . ' ';

InvalidParamDefault

Emitted when a function parameter default clashes with the type Psalm expects the param to be

function foo(int $i = false) : void {}

InvalidPassByReference

Emitted when passing a non-variable to a function that expects a by-ref variable

function foo(array &$arr) : void {}
foo([0, 1, 2]);

InvalidPropertyAssignment

Emitted when attempting to assign a property to a non-object

$a = "foo";
$a->bar = "bar";

InvalidPropertyFetch

Emitted when attempting to get a property from a non-object

$a = "foo";
echo $a->bar;

InvalidReturnStatement

Emitted when a function return statement is incorrect

function foo() : string {
    return 5; // emitted here
}

InvalidReturnType

Emitted when a functions signature return type is incorrect (often emitted with `InvalidReturnStatement`)
function foo() : int {
    if (rand(0, 1)) {
        return "hello";
    }

    return 5;
}

InvalidScalarArgument

Emitted when a scalar value is passed to a method that expected another scalar type

function foo(int $i) : void {}
function bar(string $s) : void {
    if (is_numeric($s)) {
        foo($s);
    }
}

InvalidScope

Emitted when referring to $this outside a class

echo $this;

InvalidStaticInvocation

Emitted when trying to call an instance function statically

class A {
    /** @var ?string */
    public $foo;

    public function bar() : void {
        echo $this->foo;
    }
}

A::bar();

InvalidThrow

Emitted when trying to throw a class that doesn't extend Exception or implement Throwable

class A {}
throw new A();

InvalidToString

Emitted when a __toString method does not always return a string

class A {
    public function __toString() {
        return true;
    }
}

LessSpecificReturnStatement

Emitted when a return statement is more general than the return type given for the function

class A {}
class B extends A {}

function foo() : B {
    return new A(); // emitted here
}

LessSpecificReturnType

Emitted when a return type covers more possibilities than the function itself

function foo() : ?int {
    return 5;
}

LoopInvalidation

Emitted when logic inside a loop invalidates one of the conditionals of the loop

for ($i = 0; $i < 10; $i++) {
    $i = 5;
}

MethodSignatureMismatch

Emitted when a method parameter differs from a parent method parameter, or if there are fewer parameters than the parent method

class A {
    public function foo(int $i) : void {}
}
class B extends A {
    public function foo(string $s) : void {}
}

MismatchingDocblockParamType

Emitted when an @param entry in a functions docblock doesnt match the param typehint,

class A {}
class B {}
/**
 * @param B $b // emitted here
 */
function foo(A $b) : void {}

This, however, is fine:

class A {}
class B extends A {}
/**
 * @param B
 */
function foo(A $b) : void {}

MismatchingDocblockReturnType

Emitted when an @return entry in a functions docblock doesnt match the function return typehint

class A {}
class B {}
/**
 * @return B // emitted here
 */
function foo() : A {
    return new A();
}

This, however, is fine:

class A {}
class B extends A {}
/**
 * @return B // emitted here
 */
function foo() : A {
    return new B();
}

MismatchingDocblockParamType

Emitted when an @param entry in a functions docblock doesnt match the param typehint

/**
 * @param int $b 
 */
function foo(string $b) : void {}

MisplacedRequiredParam

Emitted when a required param is before a param that is not required. Included in Psalm because it is an E_WARNING in PHP

function foo(int $i = 5, string $j) : void {}

MissingClosureReturnType

Emitted when a closure lacks a return type

$a = function() {
    return "foo";
};

MissingConstructor

Emitted when non-null properties without default values are defined in a class without a __construct method

class A {
    /** @var string */
    public $foo;
}

MissingDocblockType

Emitted when a docblock is present, but the type is missing or badly formatted

/** @var $a */
$a = [];

MissingFile

Emitted when using include or require on a file that does not exist

require("nonexistent.php");

MissingPropertyType

Emitted when a property is defined on a class without a type

class A {
    public $foo;
}

MissingReturnType

Emitted when a function doesn't have a return type defined

function foo() {
    return "foo";
}

MixedArgument

Emitted when Psalm cannot determine the type of an argument

function takesInt(int $i) : void {}
takesInt($_GET['foo']);

MixedArrayAccess

Emitted when trying to access an array offset on a value whose type Psalm cannot determine

echo $_GET['foo'][0];

MixedArrayAssignment

Emitted when trying to assign a value to an array offset on a value whose type Psalm cannot determine

$_GET['foo'][0] = "5";

MixedArrayOffset

Emitted when attempting to access an array offset where Psalm cannot determine the offset type

echo [1, 2, 3][$_GET['foo']];

MixedAssignment

Emitted when assigning a variable to a value for which Psalm cannot infer a type

$a = $_GET['foo'];

MixedInferredReturnType

Emitted when Psalm cannot determine a function's return type

function foo() : int {
    return $_GET['foo'];
}

MixedMethodCall

Emitted when calling a method on a value that Psalm cannot infer a type for

/** @param mixed $a */
function foo($a) : void {
    $a->foo();
}

MixedOperand

Emitted when Psalm cannot infer a type for an operand in any calculated expression

echo $_GET['foo'] + "hello";

MixedPropertyAssignment

Emitted when assigning a property to a value for which Psalm cannot infer a type

/** @param mixed $a */
function foo($a) : void {
    $a->foo = "bar";
}

MixedPropertyFetch

Emitted when retrieving a property on a value for which Psalm cannot infer a type

/** @param mixed $a */
function foo($a) : void {
    echo $a->foo;
}

MixedReturnStatement

Emitted when Psalm cannot determine the type of a given return statement

function foo() : int {
    return $_GET['foo']; // emitted here
}

MixedStringOffsetAssignment

Emitted when assigning a value on a string using a value for which Psalm cannot infer a type

"hello"[$_GET['foo']] = "h";

MixedTypeCoercion

Emitted when Psalm cannot be sure that part of an array/iterabble argument's type constraints can be fulfilled

function foo(array $a) : void {
    takesStringArray($a);
}

/** @param string[] $a */
function takesStringArray(array $a) : void {}

MoreSpecificImplementedReturnType

Emitted when a class implements an interface method but its return type is less specific than the interface method return type

class A {}
class B extends A {}
interface I {
    /** @return B[] */
    public function foo();
}
class D implements I {
    /** @return A[] */
    public function foo() {
        return [new A, new A];
    }
}

MoreSpecificReturnType

Emitted when the declared return type for a method is more specific than the inferred one (emitted in the same methods that LessSpecificReturnStatement is)

class A {}
class B extends A {}
function foo() : B {
    /** @psalm-suppress LessSpecificReturnStatement */
    return new A();
}

NoInterfaceProperties

Emitted when trying to fetch a property on an interface as interfaces, by definition, do not have definitions for properties.

interface I {}
class A implements I {
    /** @var ?string */
    public $foo;
}
function bar(I $i) : void {
    if ($i->foo) {}
}

NonStaticSelfCall

Emitted when


NullableReturnStatement

Emitted if a return statement contains a null value, but the function return type is not nullable

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return null; // emitted here
}

NullArgument

Emitted when calling a function with a null value argument when the function does not expect it

function foo(string $s) : void {}
foo(null);

NullArrayAccess

Emitted when trying to access an array value on null

$arr = null;
echo $arr[0];

NullArrayOffset

Emitted when trying to access an array offset with null

$arr = ['' => 5, 'foo' => 1];
echo $arr[null];

NullFunctionCall

Emitted when trying to use null as a callable

$arr = null;
echo $arr();

NullIterator

Emitted when iterating over null

foreach (null as $a) {}

NullOperand

Emitted when using null as part of an operation (e.g. +, ., ^ etc.`)

echo null . 'hello';

NullPropertyAssignment

Emitted when trying to set a property on null

$a = null;
$a->foo = "bar";

NullPropertyFetch

Emitted when trying to fetch a property on a null value

$a = null;
echo $a->foo;

NullReference

Emitted when attempting to call a method on null

$a = null;
$a->foo();

OverriddenMethodAccess

Emitted when a method is less accessible than its parent

class A {
    public function foo() : void {}
}
class B extends A {
    protected function foo() : void {}
}

ParadoxicalCondition

Emitted when a paradox is encountered in your programs logic that could not be caught by RedundantCondition

function foo(?string $a) : ?string {
    if ($a) return $a;
    if ($a) echo "cannot happen";
}

ParentNotFound

Emitted when using parent:: in a class without a parent class.

class A {
  public function foo() : void {
    parent::foo();
  }
}

PossiblyFalseArgument

Emitted when a function argument is possibly false, but the function doesnt expect false. This is distinct from a function argument is possibly bool, which results in PossiblyInvalidArgument.

function foo(string $s) : void {
    $a_pos = strpos($s, "a");
    echo substr($s, $a_pos);
}

PossiblyFalseReference

Emitted when making a method call on a value than might be false

class A {
    public function bar() : void {}
}

/** @return A|false */
function foo() {
    return rand(0, 1) ? new A : false;
}

foo()->bar();

PossiblyInvalidArgument

Emitted when

/** @return string|int */
function foo() {
    return rand(0, 1) ? 5 : "i";
}
function bar(int $i) : void {}
bar(foo());

PossiblyInvalidArrayAccess

Emitted when attempting to access an array offset on a value that may not be an array

$arr = rand(0, 1) ? 5 : [4, 3, 2, 1];
echo $arr[0];

PossiblyInvalidArrayAssignment

Emitted when attempting to assign an array offset on a value that may not be an array

$arr = rand(0, 1) ? 5 : [4, 3, 2, 1];
$arr[0] = "hello";

PossiblyInvalidArrayOffset

Emitted when its possible that the array offset is not applicable to the value youre trying to access.

$arr = rand(0, 1) ? ["a" => 5] : "hello";
echo $arr[0];

PossiblyInvalidFunctionCall

Emitted when trying to call a function on a value that may not be callable

$a = rand(0, 1) ? 5 : function() : int { return 5; };
$b = $a();

PossiblyInvalidMethodCall

Emitted when trying to call a method on a value that may not be an object

class A {
    public function bar() : void {}
}

/** @return A|int */
function foo() {
    return rand(0, 1) ? new A : 5;
}

foo()->bar();

PossiblyInvalidPropertyAssignment

Emitted when trying to assign a property on a value that may not be an object or may be an object that doesnt have the desired property.

class A {
    /** @var ?string */
    public $bar;
}

/** @return A|int */
function foo() {
    return rand(0, 1) ? new A : 5;
}

$a = foo();
$a->bar = "5";

PossiblyInvalidPropertyFetch

Emitted when trying to fetch a property on a value that may not be an object or may be an object that doesnt have the desired property.

class A {
    /** @var ?string */
    public $bar;
}

/** @return A|int */
function foo() {
    return rand(0, 1) ? new A : 5;
}

$a = foo();
echo $a->bar;

PossiblyNullArgument

Emitted when calling a function with a value thats possibly null when the function does not expect it

function foo(string $s) : void {}
foo(rand(0, 1) ? "hello" : null);

PossiblyNullArrayAccess

Emitted when trying to access an array offset on a possibly null value

function foo(?array $a) : void {
    echo $a[0];
}

PossiblyNullArrayAssignment

Emitted when trying to set a value on a possibly null array

function foo(?array $a) : void {
    $a[0] = "5";
}

PossiblyNullArrayOffset

Emitted when trying to access a value on an array using a possibly null offset

function foo(?int $a) : void {
    echo [1, 2, 3, 4][$a];
}

PossiblyNullFunctionCall

Emitted when trying to call a function on a value that may be null

function foo(?callable $a) : void {
    $a();
}

PossiblyNullIterator

Emitted when trying to iterate over a value that may be null

function foo(?array $arr) : void {
    foreach ($arr as $a) {}
}

PossiblyNullOperand

Emitted when using a possibly null value as part of an operation (e.g. +, ., ^ etc.`)

function foo(?int $a) : void {
    echo $a + 5;
}

PossiblyNullPropertyAssignment

Emitted when trying to assign a property to a possibly null object

class A {
    /** @var ?string */
    public $foo;
}
function foo(?A $a) : void {
    $a->foo = "bar";
}

PossiblyNullPropertyFetch

Emitted when trying to fetch a property on a possibly null object

class A {
    /** @var ?string */
    public $foo;
}
function foo(?A $a) : void {
    echo $a->foo;
}

PossiblyNullReference

Emitted when trying to call a method on a possibly null value

class A {
    public function bar() : void {}
}
function foo(?A $a) : void {
    $a->bar();
}

PossiblyUndefinedGlobalVariable

Emitted when trying to access a variable in the global scope that may not be defined

if (rand(0, 1)) {
  $a = 5;
}
echo $a;

PossiblyUndefinedMethod

Emitted when trying to access a method that may not be defined on the object

class A {
    public function bar() : void {}
}
class B {}

$a = rand(0, 1) ? new A : new B;
$a->bar();

PossiblyUndefinedVariable

Emitted when trying to access a variable in function scope that may not be defined

function foo() : void {
    if (rand(0, 1)) {
        $a = 5;
    }
    echo $a;
}

PossiblyUnusedMethod

Emitted when --find-dead-code is turned on and Psalm cannot find any calls to a given class method

class A {
    public function foo() : void {}
    public function bar() : void {}
}
(new A)->foo();

PossiblyUnusedParam

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a particular parameter in a public/protected method

class A {
    public function foo(int $a, int $b) : int {
        return $a + 4;
    }
}

PropertyNotSetInConstructor

Emitted when a non-null property without a default value is declared but not set in the classs constructor

class A {
    /** @var string */
    public $foo;

    public function __construct() {}
}

RawObjectIteration

Emitted when iterating over an objects properties. This issue exists because it may be undesired behaviour (e.g. you may have meant to iterate over an array)

class A {
    /** @var string */
    public $foo;

    /** @var string */
    public $bar;
}

function takesA(A $a) {
    foreach ($a as $property) {}
}

RedundantCondition

Emitted when conditional is redundant given previous assertions

class A {}
function foo(?A $a) : ?A {
    if ($a) return $a;
    if ($a) echo "cannot happen";
}

ReferenceConstraintViolation

Emitted when changing the type of a pass-by-reference variable

function foo(string &$a) {
    $a = 5;
}

ReservedWord

Emitted when using a reserved word as a class name

function foo(resource $res) : void {}

TooFewArguments

Emitted when calling a function with fewer arguments than the function has parameters

function foo(string $a) : void {}
foo();

TooManyArguments

Emitted when calling a function with more arguments than the function has parameters

function foo(string $a) : void {}
foo("hello", 4);

TypeCoercion

Emitted when calling a function with an argument which has a less specific type than the function expects

class A {}
class B extends A {}

function takesA(A $a) : void {
    takesB($a);
}
function takesB(B $b) : void {}

TypeDoesNotContainNull

Emitted when checking a non-nullable type for null

$a = "hello";
if ($a === null) {}

TypeDoesNotContainType

Emitted checking whether one value has a type or value that is impossible given its currently-known type

$a = "hello";
if ($a === 5) {}

UndefinedClass

Emitted when referencing a class that doesnt exist

$a = new A();

UndefinedConstant

Emitted when referencing a constant that doesnt exist

echo FOO_BAR;

UndefinedFunction

Emitted when referencing a function that doesn't exist

foo();

UndefinedGlobalVariable

Emitted when referencing a variable that doesn't exist

echo $a;

UndefinedMethod

Emitted when calling a method that doesnt exist

class A {}
A::foo();

UndefinedPropertyAssignment

Emitted when assigning a property on an object that doesnt have that property defined

class A {}
$a = new A();
$a->foo = "bar";

UndefinedPropertyFetch

Emitted when getting a property on an object that doesnt have that property defined

class A {}
$a = new A();
echo $a->foo;

UndefinedThisPropertyAssignment

Emitted when assigning a property on an object in one of that objects methods when no such property exists

class A {
    function foo() {
        $this->foo = "bar";
    }
}

UndefinedThisPropertyFetch

Emitted when getting a property for an object in one of that objects methods when no such property exists

class A {
    function foo() {
        echo $this->foo;
    }
}

UndefinedTrait

Emitted when referencing a trait that doesnt exist

class A {
    use T;
}

UndefinedVariable

Emitted when referencing a variable that doesn't exist in a given functions scope

function foo() {
    echo $a;
}

UnevaluatedCode

Emitted when --find-dead-code is turned on and Psalm encounters code that will not be evaluated

function foo() : void {
    return;
    $a = "foo";
}

UnimplementedAbstractMethod

Emitted when a class extends another, but does not implement all of its abstract methods

abstract class A {
    abstract public function foo();
}
class B extends A {}

UnimplementedInterfaceMethod

Emitted when a class implements an interface but does not implement all of its methods

interface I {
    public function foo();
}
class A implements I {}

UnrecognizedExpression

Emitted when Psalm encounters an expression that it doesn't know how to handle. This should never happen.

UnrecognizedStatement

Emitted when Psalm encounters a code construct that it doesn't know how to handle. This should never happen.

UnresolvableInclude

Emitted when Psalm cannot figure out what specific file is being included/required by PHP.

function requireFile(string $s) : void {
    require_once($s);
}

UntypedParam

Emitted when a function paramter has no type information associated with it

function foo($a) : void {}

UnusedClass

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a given class

class A {}
class B {}
$a = new A();

UnusedMethod

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a given private method or function

class A {
    public function __construct() {
        $this->foo();
    }
    private function foo() : void {}
    private function bar() : void {}
}
new A();

UnusedParam

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a particular parameter in a private method or function

function foo(int $a, int $b) : int {
    return $a + 4;
}

UnusedVariable

Emitted when --find-dead-code is turned on and Psalm cannot find any references to a variable, once instantiated

function foo() : void {
    $a = 5;
    $b = 4;
    echo $b;
}