2021-03-03 11:50:29 -05:00
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Aviat\Kilo\Tokens;
|
|
|
|
|
|
|
|
use PhpToken;
|
|
|
|
|
|
|
|
use function Aviat\Kilo\tabs_to_spaces;
|
2021-04-14 14:40:35 -04:00
|
|
|
use const Aviat\Kilo\T_RAW;
|
2021-03-03 11:50:29 -05:00
|
|
|
|
|
|
|
class PHP8 extends PhpToken {
|
|
|
|
private array $rawLines = [];
|
|
|
|
|
|
|
|
private array $tokens = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Use 'token_get_all' to get the tokens for a file,
|
|
|
|
* organized by row number
|
|
|
|
*
|
|
|
|
* @param string $code
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public static function getTokens(string $code): array
|
|
|
|
{
|
2021-03-04 16:41:12 -05:00
|
|
|
// Make the lines/tokens 1-indexed
|
2021-03-03 11:50:29 -05:00
|
|
|
$lines = explode("\n", $code);
|
|
|
|
array_unshift($lines, '');
|
|
|
|
unset($lines[0]);
|
|
|
|
|
|
|
|
$self = (new self(0, $code));
|
|
|
|
|
|
|
|
$self->rawLines = $lines;
|
|
|
|
$self->tokens = array_fill(1, count($lines), []);
|
|
|
|
|
|
|
|
return $self->organizeTokens($code);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return tokens for the current $filename, organized
|
|
|
|
* by row number
|
|
|
|
*
|
|
|
|
* @param string $filename
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public static function getFileTokens(string $filename): array
|
|
|
|
{
|
|
|
|
$code = @file_get_contents($filename);
|
|
|
|
|
|
|
|
if ($code === FALSE)
|
|
|
|
{
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::getTokens($code);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function organizeTokens(string $code): array
|
|
|
|
{
|
|
|
|
$rawTokens = self::tokenize($code);
|
|
|
|
foreach ($rawTokens as $t)
|
|
|
|
{
|
|
|
|
$this->processObjectToken($t);
|
|
|
|
}
|
|
|
|
|
|
|
|
ksort($this->tokens);
|
|
|
|
|
|
|
|
return $this->tokens;
|
|
|
|
}
|
|
|
|
|
2022-11-18 13:38:18 -05:00
|
|
|
protected function processObjectToken(PhpToken $token): void
|
2021-03-03 11:50:29 -05:00
|
|
|
{
|
|
|
|
$currentLine = $token->line;
|
|
|
|
$char = tabs_to_spaces($token->text);
|
|
|
|
|
|
|
|
$current = [
|
|
|
|
'type' => $token->id,
|
|
|
|
'typeName' => $token->getTokenName(),
|
|
|
|
'char' => $char,
|
|
|
|
'line' => $currentLine,
|
|
|
|
];
|
|
|
|
|
2021-03-03 16:35:58 -05:00
|
|
|
// Single new line, or starts with a new line with other whitespace
|
|
|
|
if (str_starts_with($char, "\n") && trim($char) === '')
|
|
|
|
{
|
|
|
|
$this->tokens[$currentLine][] = $current;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only return the first line of a multi-line token for this line array
|
|
|
|
if (str_contains($char, "\n"))
|
|
|
|
{
|
|
|
|
$chars = explode("\n", $char);
|
|
|
|
$current['original'] = [
|
|
|
|
'string' => $char,
|
|
|
|
'lines' => $chars,
|
|
|
|
];
|
|
|
|
$current['char'] = array_shift($chars);
|
|
|
|
|
|
|
|
// Add new lines for additional newline characters
|
|
|
|
$nextLine = $currentLine;
|
|
|
|
foreach ($chars as $char)
|
|
|
|
{
|
|
|
|
$nextLine++;
|
|
|
|
|
|
|
|
if ( ! empty($char))
|
|
|
|
{
|
|
|
|
$this->processStringToken($char, $nextLine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 11:50:29 -05:00
|
|
|
$this->tokens[$currentLine][] = $current;
|
|
|
|
}
|
2021-03-03 16:35:58 -05:00
|
|
|
|
|
|
|
protected function processStringToken(string $token, int $startLine): void
|
|
|
|
{
|
|
|
|
$char = tabs_to_spaces($token);
|
|
|
|
$lineNumber = $this->findCorrectLine($char, $startLine) ?? $startLine;
|
|
|
|
|
|
|
|
// Simple characters, usually delimiters or single character operators
|
|
|
|
$this->tokens[$lineNumber][] = [
|
2021-04-14 14:40:35 -04:00
|
|
|
'type' => T_RAW,
|
2021-03-03 16:35:58 -05:00
|
|
|
'typeName' => 'RAW',
|
|
|
|
'char' => tabs_to_spaces($token),
|
|
|
|
'line' => $lineNumber,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
private function findCorrectLine(string $search, int $rowOffset, int $searchLength = 5): ?int
|
|
|
|
{
|
|
|
|
$end = $rowOffset + $searchLength;
|
|
|
|
if ($end > count($this->rawLines))
|
|
|
|
{
|
|
|
|
$end = count($this->rawLines);
|
|
|
|
}
|
|
|
|
|
|
|
|
for ($i = $rowOffset; $i < $end; $i++)
|
|
|
|
{
|
|
|
|
if (str_contains($this->rawLines[$i], $search))
|
|
|
|
{
|
|
|
|
return $i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-03 11:50:29 -05:00
|
|
|
}
|