diff --git a/examples/plugins/ClassUnqualifier.php b/examples/plugins/ClassUnqualifier.php index 88a12bd5b..38206faa2 100644 --- a/examples/plugins/ClassUnqualifier.php +++ b/examples/plugins/ClassUnqualifier.php @@ -42,7 +42,15 @@ class ClassUnqualifier implements AfterClassLikeExistenceCheckInterface } } - $new_candidate_type = implode('', $type_tokens); + $new_candidate_type = implode( + '', + array_map( + function ($f) { + return $f[0]; + }, + $type_tokens + ) + ); if ($new_candidate_type !== $candidate_type) { $bounds = $code_location->getSelectionBounds(); diff --git a/src/Psalm/Internal/Type/ParseTree.php b/src/Psalm/Internal/Type/ParseTree.php index b71be0462..aaf0e4a02 100644 --- a/src/Psalm/Internal/Type/ParseTree.php +++ b/src/Psalm/Internal/Type/ParseTree.php @@ -501,6 +501,7 @@ class ParseTree $new_leaf = new ParseTree\Value( $type_token[0] . '::' . $nexter_token[0], + $type_token[1], $new_parent ); @@ -515,6 +516,7 @@ class ParseTree $new_leaf = new ParseTree\Value( $type_token[0], + $type_token[1], $new_parent ); break; diff --git a/src/Psalm/Internal/Type/ParseTree/Value.php b/src/Psalm/Internal/Type/ParseTree/Value.php index bf3be901c..04a581e7b 100644 --- a/src/Psalm/Internal/Type/ParseTree/Value.php +++ b/src/Psalm/Internal/Type/ParseTree/Value.php @@ -11,12 +11,18 @@ class Value extends \Psalm\Internal\Type\ParseTree */ public $value; + /** + * @var int + */ + public $offset; + /** * @param string $value * @param \Psalm\Internal\Type\ParseTree|null $parent */ - public function __construct($value, \Psalm\Internal\Type\ParseTree $parent = null) + public function __construct(string $value, int $offset, \Psalm\Internal\Type\ParseTree $parent = null) { + $this->offset = $offset; $this->value = $value; $this->parent = $parent; } diff --git a/src/Psalm/Type.php b/src/Psalm/Type.php index 74838ff54..315ed9e01 100644 --- a/src/Psalm/Type.php +++ b/src/Psalm/Type.php @@ -127,7 +127,10 @@ abstract class Type $only_token[0] = self::fixScalarTerms($only_token[0], $php_version); - return new Union([Atomic::create($only_token[0], $php_version, $template_type_map)]); + $atomic = Atomic::create($only_token[0], $php_version, $template_type_map); + $atomic->offset = 0; + + return new Union([$atomic]); } $parse_tree = ParseTree::createFromTokens($type_tokens); @@ -649,9 +652,13 @@ abstract class Type throw new TypeParseTreeException('Invalid type \'' . $parse_tree->value . '\''); } - $atomic_type = self::fixScalarTerms($parse_tree->value, $php_version); + $atomic_type_string = self::fixScalarTerms($parse_tree->value, $php_version); - return Atomic::create($atomic_type, $php_version, $template_type_map); + $atomic_type = Atomic::create($atomic_type_string, $php_version, $template_type_map); + + $atomic_type->offset = $parse_tree->offset; + + return $atomic_type; } private static function getGenericParamClass( diff --git a/src/Psalm/Type/Atomic.php b/src/Psalm/Type/Atomic.php index 99d41cd04..36b5a42a2 100644 --- a/src/Psalm/Type/Atomic.php +++ b/src/Psalm/Type/Atomic.php @@ -67,6 +67,11 @@ abstract class Atomic */ public $from_docblock = false; + /** + * @var ?int + */ + public $offset; + /** * @param string $value * @param array{int,int}|null $php_version