Skip to content
Permalink
Browse files

Fix bugs when moving methods that reference each other

  • Loading branch information...
muglug committed Jun 14, 2019
1 parent 6f6054f commit 58b6ce34836a2f48b15f2c305003cd2aa60eff04
@@ -51,8 +51,6 @@ public static function analyze(
$config = $codebase->config;
$moved_call = false;
if ($stmt->class instanceof PhpParser\Node\Name) {
$fq_class_name = null;
@@ -152,16 +150,6 @@ public static function analyze(
}
}
if ($codebase->alter_code && $fq_class_name) {
$moved_call = $codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
);
}
if ($codebase->store_node_types && $fq_class_name) {
$codebase->analyzer->addNodeReference(
$statements_analyzer->getFilePath(),
@@ -193,6 +181,7 @@ public static function analyze(
}
$has_mock = false;
$moved_call = false;
foreach ($lhs_type->getTypes() as $lhs_type_part) {
$intersection_types = [];
@@ -500,6 +489,16 @@ function (PhpParser\Node\Arg $arg) {
return false;
}
if ($codebase->alter_code && $fq_class_name && !$moved_call) {
$codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
);
}
return;
}
@@ -837,46 +836,40 @@ function (Assertion $assertion) use ($found_generic_params) : Assertion {
}
if ($codebase->alter_code) {
if (!$moved_call) {
foreach ($codebase->call_transforms as $original_pattern => $transformation) {
if ($declaring_method_id
&& strtolower($declaring_method_id) . '\((.*\))' === $original_pattern
foreach ($codebase->call_transforms as $original_pattern => $transformation) {
if ($declaring_method_id
&& strtolower($declaring_method_id) . '\((.*\))' === $original_pattern
) {
if (strpos($transformation, '($1)') === strlen($transformation) - 4
&& $stmt->class instanceof PhpParser\Node\Name
) {
if (strpos($transformation, '($1)') === strlen($transformation) - 4
&& $stmt->class instanceof PhpParser\Node\Name
) {
$new_method_id = substr($transformation, 0, -4);
list($old_declaring_fq_class_name) = explode('::', $declaring_method_id);
list($new_fq_class_name, $new_method_name) = explode('::', $new_method_id);
$file_manipulations = [];
if (strtolower($new_fq_class_name) !== strtolower($old_declaring_fq_class_name)) {
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->class->getAttribute('startFilePos'),
(int) $stmt->class->getAttribute('endFilePos') + 1,
Type::getStringFromFQCLN(
$new_fq_class_name,
$statements_analyzer->getNamespace(),
$statements_analyzer->getAliasedClassesFlipped(),
null
)
);
}
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->name->getAttribute('startFilePos'),
(int) $stmt->name->getAttribute('endFilePos') + 1,
$new_method_name
);
FileManipulationBuffer::add(
$statements_analyzer->getFilePath(),
$file_manipulations
);
$new_method_id = substr($transformation, 0, -4);
list($old_declaring_fq_class_name) = explode('::', $declaring_method_id);
list($new_fq_class_name, $new_method_name) = explode('::', $new_method_id);
if ($codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
$statements_analyzer,
$stmt->class,
$new_fq_class_name,
$context->calling_method_id,
strtolower($old_declaring_fq_class_name) !== strtolower($new_fq_class_name)
)) {
$moved_call = true;
}
$file_manipulations = [];
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->name->getAttribute('startFilePos'),
(int) $stmt->name->getAttribute('endFilePos') + 1,
$new_method_name
);
FileManipulationBuffer::add(
$statements_analyzer->getFilePath(),
$file_manipulations
);
}
}
}
@@ -935,6 +928,16 @@ function (Assertion $assertion) use ($found_generic_params) : Assertion {
}
}
if ($codebase->alter_code && $fq_class_name && !$moved_call) {
$codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
);
}
if ($codebase->store_node_types && $method_id) {
/** @psalm-suppress PossiblyInvalidArgument never a string, PHP Parser bug */
$codebase->analyzer->addNodeReference(
@@ -964,7 +964,8 @@ public function handleClassLikeReferenceInMigration(
\Psalm\StatementsSource $source,
PhpParser\Node $class_name_node,
string $fq_class_name,
?string $calling_method_id
?string $calling_method_id,
bool $force_change = false
) : bool {
$calling_fq_class_name = $source->getFQCLN();
@@ -1100,6 +1101,18 @@ public function handleClassLikeReferenceInMigration(
return true;
}
if ($force_change && $calling_fq_class_name) {
$this->airliftClassLikeReference(
$fq_class_name,
$calling_fq_class_name,
$source->getFilePath(),
(int) $class_name_node->getAttribute('startFilePos'),
(int) $class_name_node->getAttribute('endFilePos') + 1
);
return true;
}
return false;
}
@@ -54,12 +54,15 @@ private static function getCodeOffsets(
$middle_offset = 0;
foreach (self::$file_manipulations[$source_file_path] as $fm) {
$offset = strlen($fm->insertion_text) - $fm->end + $fm->start;
if ($fm->end < $source_start) {
$start_offset += strlen($fm->insertion_text) - $fm->end + $fm->start;
$start_offset += $offset;
$middle_offset += $offset;
} elseif ($fm->start > $source_start
&& $fm->end < $source_end
) {
$middle_offset += strlen($fm->insertion_text) - $fm->end + $fm->start;
$middle_offset += $offset;
}
}
@@ -140,12 +143,13 @@ public static function getMigrationManipulations(FileProvider $file_provider)
$code_migration_manipulations[$code_migration->destination_file_path] = [];
}
$code_migration_manipulations[$code_migration->source_file_path][]
= new FileManipulation(
$code_migration->source_start + $start_offset,
$code_migration->source_end + $middle_offset,
''
);
$delete_file_manipulation = new FileManipulation(
$code_migration->source_start + $start_offset,
$code_migration->source_end + $middle_offset,
''
);
$code_migration_manipulations[$code_migration->source_file_path][] = $delete_file_manipulation;
list($destination_start_offset) = self::getCodeOffsets(
$code_migration->destination_file_path,
@@ -158,8 +162,8 @@ public static function getMigrationManipulations(FileProvider $file_provider)
$code_migration->destination_start + $destination_start_offset,
PHP_EOL . substr(
$file_provider->getContents($code_migration->source_file_path),
$code_migration->source_start + $start_offset,
$code_migration->source_end - $code_migration->source_start + $middle_offset
$delete_file_manipulation->start,
$delete_file_manipulation->end - $delete_file_manipulation->start
) . PHP_EOL
);
@@ -111,8 +111,8 @@ class A {
class B {
public static function bar() : void {
B::Fe();
foreach (B::Fe() as $f) {}
self::Fe();
foreach (self::Fe() as $f) {}
}
/**
@@ -364,6 +364,87 @@ public static function Fedbca(A $a1, ?A $a2, array $a3) : A {
'Ns\A::Foo' => 'Ns\B::Fedbca',
]
],
'moveTwoStaticMethods' => [
'<?php
namespace Ns;
class A {
const C = 5;
/**
* @param self $a1
* Some description
* @param ?self
* $a2
* @param array<
* int,
* self
* > $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;
}',
'<?php
namespace Ns;
class A {
const C = 5;
}
class B {
const D = 5;
/**
* @param A $a1
* Some description
* @param null|A
* $a2
* @param array<int, A> $a3
* @return A
*/
public static function Fedbca(A $a1, ?A $a2, array $a3) : A {
echo A::C;
echo A::C;
self::Blacksheep();
self::Blacksheep();
echo self::D;
new A();
/** @var A */
$a = new A();
new self();
return $a;
}
public static function Blacksheep() : void {}
}',
[
'Ns\A::Foo' => 'Ns\B::Fedbca',
'Ns\A::Bar' => 'Ns\B::Blacksheep',
]
],
'moveInstanceMethodIntoSubclassOnly' => [
'<?php
namespace Ns;
@@ -473,7 +554,7 @@ class A {
class B {
public static function bar() : void {
B::Fe();
self::Fe();
}
/**
@@ -512,7 +593,7 @@ public static function Foo() : void {
class B {
public static function bar() : void {
B::Fe();
self::Fe();
}
/**
@@ -526,6 +607,7 @@ public static function Fe() : void {
class A {
const C = 5;
}',
[
'Ns\A::Foo' => 'Ns\B::Fe',
@@ -565,7 +647,7 @@ class A {
namespace Ns2\Ns3 {
class B {
public static function bar() : void {
B::Fe();
self::Fe();
}
/**
@@ -618,7 +700,7 @@ class A {
class B {
public static function bar() : void {
B::Fedcba();
self::Fedcba();
}
/**

0 comments on commit 58b6ce3

Please sign in to comment.
You can’t perform that action at this time.