create(ParserFactory::PREFER_PHP7); $config = new TestConfig(); $config->throw_exception = false; $config->stop_on_first_error = false; } /** * @return void */ public function setUp() { FileChecker::clearCache(); $this->project_checker = new \Psalm\Checker\ProjectChecker(); } /** * @return void */ public function testJsonOutputForReturnTypeError() { $file_contents = 'registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData()[0]; $this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('error', $issue_data['type']); $this->assertSame("The given return type 'string' for fooFoo is incorrect, got 'int'", $issue_data['message']); $this->assertSame(2, $issue_data['line_number']); $this->assertSame( 'string', substr($file_contents, $issue_data['from'], $issue_data['to'] - $issue_data['from']) ); } /** * @return void */ public function testJsonOutputForUndefinedVar() { $file_contents = 'registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData()[0]; $this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('error', $issue_data['type']); $this->assertSame('Cannot find referenced variable $b', $issue_data['message']); $this->assertSame(3, $issue_data['line_number']); $this->assertSame( '$b', substr($file_contents, $issue_data['from'], $issue_data['to'] - $issue_data['from']) ); } /** * @return void */ public function testJsonOutputForUnknownParamClass() { $file_contents = 'registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData()[0]; $this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('error', $issue_data['type']); $this->assertSame('Class or interface Badger\\Bodger does not exist', $issue_data['message']); $this->assertSame(2, $issue_data['line_number']); $this->assertSame( 'Badger\\Bodger', substr($file_contents, $issue_data['from'], $issue_data['to'] - $issue_data['from']) ); } /** * @return void */ public function testJsonOutputForMissingReturnType() { $file_contents = 'registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData()[0]; $this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('error', $issue_data['type']); $this->assertSame('Method fooFoo does not have a return type', $issue_data['message']); $this->assertSame(2, $issue_data['line_number']); $this->assertSame( 'function fooFoo() {', substr($file_contents, $issue_data['from'], $issue_data['to'] - $issue_data['from']) ); } /** * @return void */ public function testJsonOutputForWrongMultilineReturnType() { $file_contents = 'registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData()[0]; $this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('error', $issue_data['type']); $this->assertSame('The given return type \'int\' for fooFoo is incorrect, got \'string\'', $issue_data['message']); $this->assertSame(3, $issue_data['line_number']); $this->assertSame( '@return int', substr($file_contents, $issue_data['from'], $issue_data['to'] - $issue_data['from']) ); } /** * @return void */ public function testJsonOutputForWrongSingleLineReturnType() { $file_contents = 'registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData()[0]; $this->assertSame('somefile.php', $issue_data['file_path']); $this->assertSame('error', $issue_data['type']); $this->assertSame('The given return type \'int\' for fooFoo is incorrect, got \'string\'', $issue_data['message']); $this->assertSame(2, $issue_data['line_number']); $this->assertSame( '@return int', substr($file_contents, $issue_data['from'], $issue_data['to'] - $issue_data['from']) ); } /** * @return void */ public function testJsonOutputForGetPsalmDotOrg() { $file_contents = ' 10) { $a = 5; } else { //$a = 2; } echo $a;'; $project_checker = new ProjectChecker(false, true, ProjectChecker::TYPE_JSON); $project_checker->registerFile( 'somefile.php', $file_contents ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $issue_data = IssueBuffer::getIssueData(); $this->assertEquals( [ [ 'type' => 'error', 'line_number' => 7, 'message' => 'Const CHANGE_ME is not defined', 'file_name' => 'somefile.php', 'file_path' => 'somefile.php', 'snippet' => 'echo CHANGE_ME;', 'from' => 126, 'to' => 135, ], [ 'type' => 'error', 'line_number' => 15, 'message' => 'Possibly undefined variable $a, first seen on line 10', 'file_name' => 'somefile.php', 'file_path' => 'somefile.php', 'snippet' => 'echo $a', 'from' => 202, 'to' => 204, ], [ 'type' => 'error', 'line_number' => 3, 'message' => 'Cannot find referenced variable $as_you', 'file_name' => 'somefile.php', 'file_path' => 'somefile.php', 'snippet' => ' return $as_you . "type";', 'from' => 67, 'to' => 74, ], [ 'type' => 'error', 'line_number' => 2, 'message' => 'Could not verify return type \'string|null\' for psalmCanVerify', 'file_name' => 'somefile.php', 'file_path' => 'somefile.php', 'snippet' => 'function psalmCanVerify(int $your_code) : ?string { return $as_you . "type"; }', 'from' => 48, 'to' => 55, ], ], $issue_data ); } }