Skip to content
Permalink
Browse files

Add offsets to type tokenisation

Ref #1832
  • Loading branch information...
muglug committed Jun 23, 2019
1 parent 78588ce commit 31c8a2e4d7baab7977bb222e37d74c3580a0265f
@@ -35,10 +35,10 @@ public static function afterClassLikeExistenceCheck(
$type_tokens = Type::tokenize($candidate_type, false);
foreach ($type_tokens as &$type_token) {
if ($type_token === ('\\' . $fq_class_name)
if ($type_token[0] === ('\\' . $fq_class_name)
&& isset($aliases[strtolower($fq_class_name)])
) {
$type_token = $aliases[strtolower($fq_class_name)];
$type_token[0] = $aliases[strtolower($fq_class_name)];
}
}
@@ -24,7 +24,7 @@ class CommentAnalyzer
/**
* @param array<string, array<string, array{Type\Union}>>|null $template_type_map
* @param array<string, array<int, string>> $type_aliases
* @param array<string, array<int, array{0: string, 1: int}>> $type_aliases
*
* @throws DocblockParseException if there was a problem parsing the docblock
*
@@ -115,7 +115,7 @@ public static function getTypeFromComment(
$defined_type = Type::parseTokens($var_type_tokens, null, $template_type_map ?: []);
} catch (TypeParseTreeException $e) {
throw new DocblockParseException(
implode('', $var_type_tokens) .
$line_parts[0] .
' is not a valid type' .
' (from ' .
$source->getFilePath() .
@@ -159,11 +159,11 @@ public static function getTypeFromComment(
/**
* @param Aliases $aliases
* @param array<string, array<int, string>> $type_aliases
* @param array<string, array<int, array{0: string, 1: int}>> $type_aliases
*
* @throws DocblockParseException if there was a problem parsing the docblock
*
* @return array<string, array<int, string>>
* @return array<string, array<int, array{0: string, 1: int}>>
*/
public static function getTypeAliasesFromComment(
PhpParser\Comment\Doc $comment,
@@ -186,11 +186,11 @@ public static function getTypeAliasesFromComment(
/**
* @param array<string> $type_alias_comment_lines
* @param Aliases $aliases
* @param array<string, array<int, string>> $type_aliases
* @param array<string, array<int, array{0: string, 1: int}>> $type_aliases
*
* @throws DocblockParseException if there was a problem parsing the docblock
*
* @return array<string, array<int, string>>
* @return array<string, array<int, array{0: string, 1: int}>>
*/
private static function getTypeAliasesFromCommentLines(
array $type_alias_comment_lines,
@@ -753,12 +753,12 @@ public static function analyzeInstance(
$type_tokens = Type::tokenize((string)$class_property_type);
foreach ($type_tokens as &$type_token) {
if (isset($class_template_params[$type_token])) {
$type_token = $class_template_params[$type_token];
if (isset($class_template_params[$type_token[0]])) {
$type_token[0] = $class_template_params[$type_token[0]];
}
}
$class_property_type = Type::parseString(implode('', $type_tokens));
$class_property_type = Type::parseTokens($type_tokens);
}
}
}
@@ -39,7 +39,7 @@ public function __destruct()
/**
* Create a parse tree from a tokenised type
*
* @param array<int, string> $type_tokens
* @param array<int, array{0: string, 1: int}> $type_tokens
*
* @return self
*/
@@ -55,38 +55,38 @@ public static function createFromTokens(array $type_tokens)
$type_token = $type_tokens[$i];
$next_token = $i + 1 < $c ? $type_tokens[$i + 1] : null;
switch ($type_token) {
switch ($type_token[0]) {
case '<':
case '{':
case ']':
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
case '[':
if ($current_leaf instanceof ParseTree\Root) {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
$indexed_access = false;
if ($next_token !== ']') {
if (!$next_token || $next_token[0] !== ']') {
$next_next_token = $i + 2 < $c ? $type_tokens[$i + 2] : null;
if ($next_next_token === ']') {
if ($next_next_token !== null && $next_next_token[0] === ']') {
$indexed_access = true;
++$i;
} else {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
}
$current_parent = $current_leaf->parent;
if ($indexed_access) {
if (!$next_token) {
throw new TypeParseTreeException('Unexpected token ' . $next_token);
if ($next_token === null) {
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
$new_parent_leaf = new ParseTree\IndexedAccessTree($next_token, $current_parent);
$new_parent_leaf = new ParseTree\IndexedAccessTree($next_token[0], $current_parent);
} else {
$new_parent_leaf = new ParseTree\GenericTree('array', $current_parent);
}
@@ -129,7 +129,10 @@ public static function createFromTokens(array $type_tokens)
break;
case ')':
if ($last_token === '(' && $current_leaf instanceof ParseTree\CallableTree) {
if ($last_token !== null
&& $last_token[0] === '('
&& $current_leaf instanceof ParseTree\CallableTree
) {
break;
}
@@ -169,7 +172,7 @@ public static function createFromTokens(array $type_tokens)
case ',':
if ($current_leaf instanceof ParseTree\Root) {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
if (!$current_leaf->parent) {
@@ -205,13 +208,13 @@ public static function createFromTokens(array $type_tokens)
case '...':
case '=':
if ($last_token === '...' || $last_token === '=') {
if ($last_token && ($last_token[0] === '...' || $last_token[0] === '=')) {
throw new TypeParseTreeException('Cannot have duplicate tokens');
}
$current_parent = $current_leaf->parent;
if ($current_leaf instanceof ParseTree\MethodTree && $type_token === '...') {
if ($current_leaf instanceof ParseTree\MethodTree && $type_token[0] === '...') {
self::createMethodParam($current_leaf, $current_leaf, $type_tokens, $type_token, $i);
break;
}
@@ -225,16 +228,16 @@ public static function createFromTokens(array $type_tokens)
}
if (!$current_parent || !$current_leaf) {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
if ($current_parent instanceof ParseTree\CallableParamTree) {
throw new TypeParseTreeException('Cannot have variadic param with a default');
}
$new_leaf = new ParseTree\CallableParamTree($current_parent);
$new_leaf->has_default = $type_token === '=';
$new_leaf->variadic = $type_token === '...';
$new_leaf->has_default = $type_token[0] === '=';
$new_leaf->variadic = $type_token[0] === '...';
$new_leaf->children = [$current_leaf];
$current_leaf->parent = $new_leaf;
@@ -248,7 +251,7 @@ public static function createFromTokens(array $type_tokens)
case ':':
if ($current_leaf instanceof ParseTree\Root) {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
$current_parent = $current_leaf->parent;
@@ -302,7 +305,7 @@ public static function createFromTokens(array $type_tokens)
}
$new_parent_leaf = new ParseTree\ObjectLikePropertyTree($current_leaf->value, $current_parent);
$new_parent_leaf->possibly_undefined = $last_token === '?';
$new_parent_leaf->possibly_undefined = $last_token !== null && $last_token[0] === '?';
$current_leaf->parent = $new_parent_leaf;
array_pop($current_parent->children);
@@ -335,7 +338,7 @@ public static function createFromTokens(array $type_tokens)
break;
case '?':
if ($next_token !== ':') {
if ($next_token === null || $next_token[0] !== ':') {
$new_parent = !$current_leaf instanceof ParseTree\Root ? $current_leaf : null;
$new_leaf = new ParseTree\NullableTree(
@@ -358,7 +361,7 @@ public static function createFromTokens(array $type_tokens)
case '|':
if ($current_leaf instanceof ParseTree\Root) {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
$current_parent = $current_leaf->parent;
@@ -374,7 +377,7 @@ public static function createFromTokens(array $type_tokens)
}
if ($current_leaf instanceof ParseTree\UnionTree) {
throw new TypeParseTreeException('Unexpected token ' . $type_token);
throw new TypeParseTreeException('Unexpected token ' . $type_token[0]);
}
if ($current_parent && $current_parent instanceof ParseTree\UnionTree) {
@@ -439,40 +442,40 @@ public static function createFromTokens(array $type_tokens)
default:
$new_parent = !$current_leaf instanceof ParseTree\Root ? $current_leaf : null;
if ($current_leaf instanceof ParseTree\MethodTree && $type_token[0] === '$') {
if ($current_leaf instanceof ParseTree\MethodTree && $type_token[0][0] === '$') {
self::createMethodParam($current_leaf, $current_leaf, $type_tokens, $type_token, $i);
break;
}
switch ($next_token) {
switch ($next_token[0] ?? null) {
case '<':
$new_leaf = new ParseTree\GenericTree(
$type_token,
$type_token[0],
$new_parent
);
++$i;
break;
case '{':
$new_leaf = new ParseTree\ObjectLikeTree(
$type_token,
$type_token[0],
$new_parent
);
++$i;
break;
case '(':
if (in_array(strtolower($type_token), ['closure', 'callable', '\closure'])) {
if (in_array(strtolower($type_token[0]), ['closure', 'callable', '\closure'])) {
$new_leaf = new ParseTree\CallableTree(
$type_token,
$type_token[0],
$new_parent
);
} elseif ($type_token !== 'array'
&& $type_token[0] !== '\\'
} elseif ($type_token[0] !== 'array'
&& $type_token[0][0] !== '\\'
&& $current_leaf instanceof ParseTree\Root
) {
$new_leaf = new ParseTree\MethodTree(
$type_token,
$type_token[0],
$new_parent
);
} else {
@@ -488,16 +491,16 @@ public static function createFromTokens(array $type_tokens)
$nexter_token = $i + 2 < $c ? $type_tokens[$i + 2] : null;
if (!$nexter_token
|| (!preg_match('/^[A-Z_][A-Z_0-9]*$/', $nexter_token)
&& strtolower($nexter_token) !== 'class')
|| (!preg_match('/^[A-Z_][A-Z_0-9]*$/', $nexter_token[0])
&& strtolower($nexter_token[0]) !== 'class')
) {
throw new TypeParseTreeException(
'Invalid class constant ' . $nexter_token
'Invalid class constant'
);
}
$new_leaf = new ParseTree\Value(
$type_token . '::' . $nexter_token,
$type_token[0] . '::' . $nexter_token[0],
$new_parent
);
@@ -506,12 +509,12 @@ public static function createFromTokens(array $type_tokens)
break;
default:
if ($type_token === '$this') {
$type_token = 'static';
if ($type_token[0] === '$this') {
$type_token[0] = 'static';
}
$new_leaf = new ParseTree\Value(
$type_token,
$type_token[0],
$new_parent
);
break;
@@ -547,8 +550,8 @@ public static function createFromTokens(array $type_tokens)
/**
* @param ParseTree &$current_leaf
* @param ParseTree $current_parent
* @param array<int, string> $type_tokens
* @param string $current_token
* @param array<int, array{0: string, 1: int}> $type_tokens
* @param array{0: string, 1: int} $current_token
* @param int &$i
*
* @return void
@@ -557,7 +560,7 @@ private static function createMethodParam(
ParseTree &$current_leaf,
ParseTree $current_parent,
array $type_tokens,
$current_token,
array $current_token,
&$i
) {
$byref = false;
@@ -567,23 +570,23 @@ private static function createMethodParam(
$c = count($type_tokens);
if ($current_token === '&') {
if ($current_token[0] === '&') {
throw new TypeParseTreeException('Magic args cannot be passed by reference');
}
if ($current_token === '...') {
if ($current_token[0] === '...') {
$variadic = true;
++$i;
$current_token = $i < $c ? $type_tokens[$i] : null;
}
if (!$current_token || $current_token[0] !== '$') {
throw new TypeParseTreeException('Unexpected token after space ' . $current_token);
if (!$current_token || $current_token[0][0] !== '$') {
throw new TypeParseTreeException('Unexpected token after space');
}
$new_parent_leaf = new ParseTree\MethodParamTree(
$current_token,
$current_token[0],
$byref,
$variadic,
$current_parent
@@ -592,18 +595,18 @@ private static function createMethodParam(
for ($j = $i + 1; $j < $c; ++$j) {
$ahead_type_token = $type_tokens[$j];
if ($ahead_type_token === ','
|| ($ahead_type_token === ')' && $type_tokens[$j - 1] !== '(')
if ($ahead_type_token[0] === ','
|| ($ahead_type_token[0] === ')' && $type_tokens[$j - 1][0] !== '(')
) {
$i = $j - 1;
break;
}
if ($has_default) {
$default .= $ahead_type_token;
$default .= $ahead_type_token[0];
}
if ($ahead_type_token === '=') {
if ($ahead_type_token[0] === '=') {
$has_default = true;
continue;
}

0 comments on commit 31c8a2e

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