file_provider = new Provider\FakeFileProvider(); } /** * @dataProvider providerValidCodeParse * * @param string $input_code * @param string $output_code * @param array $methods_to_move * @param array $call_transforms * * @return void */ public function testValidCode( string $input_code, string $output_code, array $methods_to_move, array $call_transforms ) { $test_name = $this->getTestName(); if (strpos($test_name, 'SKIPPED-') !== false) { $this->markTestSkipped('Skipped due to a bug.'); } $config = new TestConfig(); $this->project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer( $config, new \Psalm\Internal\Provider\Providers( $this->file_provider, new Provider\FakeParserCacheProvider() ) ); $context = new Context(); $file_path = self::$src_dir_path . 'somefile.php'; $this->addFile( $file_path, $input_code ); $codebase = $this->project_analyzer->getCodebase(); $codebase->methods_to_move = $methods_to_move; $codebase->call_transforms = $call_transforms; $this->project_analyzer->refactorCodeAfterCompletion(); $this->analyzeFile($file_path, $context); $this->project_analyzer->prepareMigration(); $codebase->analyzer->updateFile($file_path, false); $this->project_analyzer->migrateCode(); $this->assertSame($output_code, $codebase->getFileContents($file_path)); } /** * @return array,array}> */ public function providerValidCodeParse() { return [ 'moveStaticMethodReferenceOnly' => [ ' */ public static function Foo() { return new ArrayObject([self::C]); } } class B { public static function bar() : void { A::Foo(); foreach (A::Foo() as $f) {} } }', ' */ public static function Foo() { return new ArrayObject([self::C]); } } class B { public static function bar() : void { B::Fe(); foreach (B::Fe() as $f) {} } }', [], [ 'ns\a::foo\((.*\))' => 'Ns\B::Fe($1)', ] ], 'moveStaticMethodReferenceOnlyIntoNamespaceWithExistingUse' => [ ' 'Ns\A\B::Fedcba($1)', ] ], 'moveEmptyStaticMethodOnly' => [ ' 'Ns\B::Fedcba', ], [ ] ], 'moveStaticMethodOnly' => [ ' $a3 * @return self */ public static function Foo(self $a1, ?self $a2, array $a3) : self { echo self::C; echo A::C; self::Bar(); A::Bar(); echo \Ns\B::D; new A(); /** @var self */ $a = new self(); new B(); return $a; } public static function Bar() : void {} } class B { const D = 5; }', ' $a3 * @return A */ public static function Fedbca(A $a1, ?A $a2, array $a3) : A { echo A::C; echo A::C; A::Bar(); A::Bar(); echo self::D; new A(); /** @var A */ $a = new A(); new self(); return $a; } }', [ 'ns\a::foo' => 'Ns\B::Fedbca', ], [] ], 'moveStaticMethodAndReferencesFromAbove' => [ ' 'Ns\B::Fe', ], [ 'ns\a::foo\((.*\))' => 'Ns\B::Fe($1)', ] ], 'moveStaticMethodAndReferencesFromBelow' => [ ' 'Ns\B::Fe', ], [ 'ns\a::foo\((.*\))' => 'Ns\B::Fe($1)', ] ], 'moveStaticMethodAndReferencesAcrossNamespaces' => [ ' 'Ns2\Ns3\B::Fe', ], [ 'ns1\a::foo\((.*\))' => 'Ns2\Ns3\B::Fe($1)', ] ], 'moveStaticMethodAndReferencesAcrossNamespacesWithExistingUse' => [ ' 'Ns2\Ns3\B::Fedcba', ], [ 'ns1\a::foo\((.*\))' => 'Ns2\Ns3\B::Fedcba($1)', ] ], ]; } }