A static analysis engine
Usage:
bin/tuli analyze file1 file2 path
Install it as a composer dependency!!!
$ composer require ircmaxell/tuli dev-master
Then simply execute vendor/bin/tuli
as normal
Or check it out into its own project. Then composer install
the dependencies:
$ composer install
Then simply bin/tuli
to execute.
code.php:
<?php
$a = 1.0;
$b = 2;
$c = foo($a, $b);
$d = foo($b, $c);
function foo(int $a, int $b): int {
if ($a > $b) {
return $a + $b + 0.5;
}
}
Then, in shell:
$ bin/tuli analyze code.php
Analyzing code.php
Determining Variable Types
Round 1 (15 unresolved variables out of 20)
.
Detecting Type Conversion Issues
Type mismatch on foo() argument 0, found float expecting int code.php:6
Type mismatch on foo() return value, found float expecting int code.php:12
Default return found for non-null type int code.php:10
Done
The three errors it found are:
Type mismatch on foo() argument 0, found float expecting int code.php:6
Meaning that at code.php on line 6, you’re passing a float to the first argument when it declared an integer
Type mismatch on foo() return value, found float expecting int code.php:12
The value that’s being returned on line 12 is a float, but it was declared as an integer in the function signature.
Default return found for non-null type int code.php:10
There’s a default return statement (not supplied) for a typed function
That’s it!
Function Argument Types
It will check all typed function arguments and determine if all calls to that function match the type.
Function Return Types
If the function’s return value is typed, it will determine if the function actually returns that type.
Method Argument Types
It will check all calls to a method for every valid typehint permutation to determine if there’s a possible mismatch.
Todo:
<?php
class A {
public function foo(int $a) : int {
return $a;
}
}
class B extends A {
public function foo(float $a) : float {
return $a;
}
}
class C extends B {
public function foo(int $a) : int {
return $a;
}
}
function foo(A $a) : int {
return $a->foo(1.0);
}
Running:
$ bin/tuli analyze code.php
Analyzing code.php
Determining Variable Types
Round 1 (5 unresolved variables out of 7)
Round 2 (3 unresolved variables out of 7)
Detecting Type Conversion Issues
Detecting Function Argument Errors
Detecting Function Return Errors
Type mismatch on foo() return value, found float expecting int code.php:22
Detecting Method Argument Errors
Type mismatch on A->foo() argument 0, found float expecting int code.php:22
Type mismatch on C->foo() argument 0, found float expecting int code.php:22
Done
Again, it found 3 errors:
Type mismatch on foo() return value, found float expecting int code.php:22
It looked at all possible A::foo()
method definitions (A::foo, B::foo, C::foo), and it detmermined that the general return type is float (since type widening allows int to be passed to float, but not the other way around). Therefore, returning ->foo() directly can result in a type error.
Type mismatch on A->foo() argument 0, found float expecting int code.php:22
Type mismatch on C->foo() argument 0, found float expecting int code.php:22
We know that if you use type A or C, you’re trying to pass a float to something that declares an integer.