1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00
psalm/tests/AnnotationTest.php

456 lines
15 KiB
PHP
Raw Normal View History

2016-12-12 05:41:11 +01:00
<?php
namespace Psalm\Tests;
use Psalm\Checker\FileChecker;
use Psalm\Context;
class AnnotationTest extends TestCase
2016-12-12 05:41:11 +01:00
{
use Traits\FileCheckerInvalidCodeParseTestTrait;
use Traits\FileCheckerValidCodeParseTestTrait;
2017-01-13 20:07:23 +01:00
/**
* @return void
*/
public function testNopType()
{
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
$this->addFile(
'somefile.php',
'<?php
$a = "hello";
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
/** @var int $a */
'
);
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
$file_checker = new FileChecker('somefile.php', $this->project_checker);
$context = new Context();
$file_checker->visitAndAnalyzeMethods($context);
2017-05-27 02:05:57 +02:00
$this->assertSame('int', (string) $context->vars_in_scope['$a']);
}
2016-12-31 06:14:00 +01:00
/**
* @return array
*/
public function providerFileCheckerValidCodeParse()
{
return [
'deprecatedMethod' => [
'<?php
class Foo {
/**
* @deprecated
*/
public static function barBar() : void {
}
2017-05-27 02:05:57 +02:00
}',
],
'validDocblockReturn' => [
'<?php
/**
* @return string
*/
function fooFoo() : string {
return "boop";
}
/**
* @return array<int, string>
*/
function foo2() : array {
return ["hello"];
}
/**
* @return array<int, string>
*/
function foo3() : array {
return ["hello"];
2017-05-27 02:05:57 +02:00
}',
],
'reassertWithIs' => [
'<?php
/** @param array $a */
function foo($a) : void {
if (is_array($a)) {
// do something
}
2017-05-27 02:05:57 +02:00
}',
],
'checkArrayWithIs' => [
'<?php
/** @param mixed $b */
function foo($b) : void {
/** @var array */
$a = (array)$b;
if (is_array($a)) {
// do something
}
2017-05-27 02:05:57 +02:00
}',
],
'checkArrayWithIsInsideLoop' => [
'<?php
/** @param array<mixed, array<mixed, mixed>> $data */
function foo($data) : void {
foreach ($data as $key => $val) {
if (!\is_array($data)) {
$data = [$key => null];
} else {
$data[$key] = !empty($val);
}
}
2017-05-27 02:05:57 +02:00
}',
],
'goodDocblock' => [
'<?php
class A {
/**
* @param A $a
* @param bool $b
*/
public function g(A $a, $b) : void {
}
2017-05-27 02:05:57 +02:00
}',
],
'goodDocblockInNamespace' => [
'<?php
namespace Foo;
class A {
/**
* @param \Foo\A $a
* @param bool $b
*/
public function g(A $a, $b) : void {
}
2017-05-27 02:05:57 +02:00
}',
],
'propertyDocblock' => [
'<?php
/**
* @property string $foo
*/
class A {
/** @param string $name */
public function __get($name) : ?string {
if ($name === "foo") {
return "hello";
}
}
/**
* @param string $name
* @param mixed $value
*/
public function __set($name, $value) : void {
}
}
$a = new A();
2017-05-27 02:05:57 +02:00
$a->foo = "hello";',
],
'ignoreNullableReturn' => [
'<?php
class A {
/** @var int */
public $bar = 5;
public function foo() : void {}
}
/**
* @return ?A
* @psalm-ignore-nullable-return
*/
function makeA() {
return rand(0, 1) ? new A() : null;
}
function takeA(A $a) : void { }
$a = makeA();
$a->foo();
$a->bar = 7;
2017-05-27 02:05:57 +02:00
takeA($a);',
],
'invalidDocblockParamSuppress' => [
'<?php
/**
* @param int $bar
* @psalm-suppress InvalidDocblock
*/
function fooFoo(array $bar) : void {
}',
],
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
'differentDocblockParamClassSuppress' => [
'<?php
class A {}
/**
* @param B $bar
* @psalm-suppress InvalidDocblock
*/
function fooFoo(A $bar) : void {
}',
],
'varDocblock' => [
'<?php
/** @var array<Exception> */
$a = [];
$a[0]->getMessage();',
],
'mixedDocblockParamTypeDefinedInParent' => [
'<?php
class A {
/** @param mixed $a */
public function foo($a) : void {}
}
class B extends A {
public function foo($a) : void {}
}',
],
'intDocblockParamTypeDefinedInParent' => [
'<?php
class A {
/** @param int $a */
public function foo($a) : void {}
}
class B extends A {
public function foo($a) : void {}
}',
],
];
}
/**
* @return array
*/
public function providerFileCheckerInvalidCodeParse()
{
return [
'invalidReturn' => [
'<?php
interface I {
/**
* @return $thus
*/
public static function barBar();
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'InvalidDocblock',
],
'invalidReturnClass' => [
'<?php
interface I {
/**
* @return 1
*/
public static function barBar();
}',
'error_message' => 'InvalidDocblock',
],
'invalidReturnClassWithComma' => [
'<?php
interface I {
/**
* @return 1,
*/
public static function barBar();
}',
'error_message' => 'InvalidDocblock',
],
'returnClassWithComma' => [
'<?php
interface I {
/**
* @return a,
*/
public static function barBar();
}',
'error_message' => 'InvalidDocblock',
],
'deprecatedMethodWithCall' => [
'<?php
class Foo {
/**
* @deprecated
*/
public static function barBar() : void {
}
}
Foo::barBar();',
2017-05-27 02:05:57 +02:00
'error_message' => 'DeprecatedMethod',
],
2017-05-25 06:34:39 +02:00
'deprecatedClassWithStaticCall' => [
'<?php
/**
* @deprecated
*/
class Foo {
public static function barBar() : void {
}
}
Foo::barBar();',
2017-05-27 02:05:57 +02:00
'error_message' => 'DeprecatedClass',
2017-05-25 06:34:39 +02:00
],
'deprecatedClassWithNew' => [
'<?php
/**
* @deprecated
*/
class Foo { }
$a = new Foo();',
2017-05-27 02:05:57 +02:00
'error_message' => 'DeprecatedClass',
2017-05-25 06:34:39 +02:00
],
'deprecatedPropertyGet' => [
'<?php
class A{
/**
* @deprecated
* @var ?int
*/
public $foo;
}
echo (new A)->foo;',
2017-05-27 02:05:57 +02:00
'error_message' => 'DeprecatedProperty',
],
'deprecatedPropertySet' => [
'<?php
class A{
/**
* @deprecated
* @var ?int
*/
public $foo;
}
$a = new A;
$a->foo = 5;',
2017-05-27 02:05:57 +02:00
'error_message' => 'DeprecatedProperty',
],
'missingParamType' => [
'<?php
/**
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
* @param string $bar
*/
function fooBar() : void {
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
}
fooBar("hello");',
'error_message' => 'TooManyArguments',
],
'missingParamVar' => [
'<?php
/**
* @param string
*/
function fooBar() : void {
}',
2017-07-27 03:30:01 +02:00
'error_message' => 'InvalidDocblock - src/somefile.php:5 - Badly-formatted @param',
],
'invalidDocblockReturn' => [
'<?php
/**
* @return string
*/
Refactor scanning and analysis, introducing multithreading (#191) * Add failing test * Add visitor to soup up classlike references * Move a whole bunch of code into the visitor * Move some methods back, move onto analysis stage * Use the getAliases method everywhere * Fix refs * Fix more refs * Fix some tests * Fix more tests * Fix include tests * Shift config class finding to project checker and fix bugs * Fix a few more tests * transition test to new syntax * Remove var_dump * Delete a bunch of code and fix mutation test * Remove unnecessary visitation * Transition to better mocked out file provider, breaking some cached statement loading * Use different scheme for naming anonymous classes * Fix anonymous class issues * Refactor file/statement loading * Add specific property types * Fix mapped property assignment * Improve how we deal with traits * Fix trait checking * Pass Psalm checks * Add multi-process support * Delay console output until the end * Remove PHP 7 syntax * Update file storage with classes * Fix scanning individual files and add reflection return types * Always turn XDebug off * Add quicker method of getting method mutations * Queue return types for crawling * Interpret all strings as possible classes once we see a `get_class` call * Check invalid return types again * Fix template namespacing issues * Default to class-insensitive file names for includes * Don’t overwrite existing issues data * Add var docblocks for scanning * Add null check * Fix loading of external classes in templates * Only try to populate class when we haven’t yet seen it’s not a class * Fix trait property accessibility * Only ever improve docblock param type * Make param replacement more robust * Fix static const missing inferred type * Fix a few more tests * Register constant definitions * Fix trait aliasing * Skip constant type tests for now * Fix linting issues * Make sure caching is off for tests * Remove unnecessary return * Use emulative parser if on PHP 5.6 * Cache parser for faster first-time parse * Fix constant resolution when scanning classes * Remove test that’s beyond a practical scope * Add back --diff support * Add --help for --threads * Remove unused vars
2017-07-25 22:11:02 +02:00
function fooFoo() : int {
return 5;
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'InvalidDocblock',
],
'propertyDocblockInvalidAssignment' => [
'<?php
/**
* @property string $foo
*/
class A {
public function __get($name) : ?string {
if ($name === "foo") {
return "hello";
}
}
public function __set($name, $value) : void {
}
}
$a = new A();
$a->foo = 5;',
'error_message' => 'InvalidPropertyAssignment',
],
'noStringParamType' => [
'<?php
function fooFoo($a) : void {
echo substr($a, 4, 2);
}',
'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be string',
'error_levels' => ['MixedArgument'],
],
'noParamTypeButConcat' => [
'<?php
function fooFoo($a) : void {
echo $a . "foo";
}',
'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be string',
'error_levels' => ['MixedOperand'],
],
'noStringIntParamType' => [
'<?php
function fooFoo($a) : void {
if (is_string($a)) {
echo substr($a, 4, 2);
} else {
echo substr("hello", $a, 2);
}
}',
'error_message' => 'UntypedParam - src/somefile.php:2 - Parameter $a has no provided type,'
. ' should be int|string',
'error_levels' => ['MixedArgument'],
],
'intParamTypeDefinedInParent' => [
'<?php
class A {
public function foo(int $a) : void {}
}
class B extends A {
public function foo($a) : void {}
}',
'error_message' => 'UntypedParam',
'error_levels' => ['MethodSignatureMismatch'],
],
'alreadyHasCheck' => [
'<?php
function takesString(string $s) : void {}
function shouldTakeString($s) : void {
if (is_string($s)) takesString($s);
}',
'error_message' => 'UntypedParam - src/somefile.php:4 - Parameter $s has no provided type,'
. ' could not infer',
'error_levels' => ['MixedArgument'],
],
'isSetBeforeInferrence' => [
'input' => '<?php
function takesString(string $s) : void {}
/** @return mixed */
function returnsMixed() {}
function shouldTakeString($s) : void {
$s = returnsMixed();
takesString($s);
}',
'error_message' => 'UntypedParam - src/somefile.php:7 - Parameter $s has no provided type,'
. ' could not infer',
'error_levels' => ['MixedArgument', 'InvalidReturnType', 'MixedAssignment'],
],
];
2016-12-31 06:14:00 +01:00
}
2016-12-12 05:41:11 +01:00
}