Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
7 / 7 |
CRAP | |
100.00% |
56 / 56 |
PHP | |
100.00% |
1 / 1 |
|
100.00% |
7 / 7 |
21 | |
100.00% |
56 / 56 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
6 / 6 |
|||
getTokens | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getFileTokens | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
organizeTokens | |
100.00% |
1 / 1 |
4 | |
100.00% |
8 / 8 |
|||
processArrayToken | |
100.00% |
1 / 1 |
6 | |
100.00% |
23 / 23 |
|||
processStringToken | |
100.00% |
1 / 1 |
2 | |
100.00% |
7 / 7 |
|||
findCorrectLine | |
100.00% |
1 / 1 |
5 | |
100.00% |
7 / 7 |
<?php declare(strict_types=1); | |
namespace Aviat\Kilo\Tokens; | |
use function Aviat\Kilo\str_contains; | |
use function Aviat\Kilo\tabs_to_spaces; | |
class PHP { | |
private string $code; | |
private array $rawLines; | |
private array $tokens; | |
private int $lineNum = 1; | |
private function __construct(string $code) | |
{ | |
$lines = explode("\n", $code); | |
array_unshift($lines, ''); | |
unset($lines[0]); | |
$this->code = $code; | |
$this->rawLines = $lines; | |
$this->tokens = array_fill(1, count($lines), []); | |
} | |
/** | |
* 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 | |
{ | |
return (new self($code))->organizeTokens(); | |
} | |
/** | |
* 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(): array | |
{ | |
$rawTokens = token_get_all($this->code); | |
foreach ($rawTokens as $t) | |
{ | |
if (is_array($t)) | |
{ | |
$this->processArrayToken($t); | |
} | |
else if (is_string($t)) | |
{ | |
$this->processStringToken($t); | |
} | |
} | |
ksort($this->tokens); | |
return $this->tokens; | |
} | |
protected function processArrayToken(array $token): void | |
{ | |
[$type, $rawChar, $currentLine] = $token; | |
$char = tabs_to_spaces($rawChar); | |
$this->lineNum = $currentLine; | |
$current = [ | |
'type' => $type, | |
'typeName' => token_name($type), | |
'char' => $char, | |
'line' => $currentLine, | |
]; | |
// Single new line, or starts with a new line with other whitespace | |
if (strpos($char, "\n") === 0 && trim($char) === '') | |
{ | |
$this->tokens[$this->lineNum][] = $current; | |
$this->lineNum++; | |
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); | |
} | |
} | |
} | |
$this->tokens[$this->lineNum][] = $current; | |
} | |
protected function processStringToken(string $token, ?int $startLine = NULL): void | |
{ | |
$char = tabs_to_spaces($token); | |
$startLine = $startLine ?? $this->lineNum; | |
$lineNumber = $this->findCorrectLine($char, $startLine) ?? $startLine; | |
// Simple characters, usually delimiters or single character operators | |
$this->tokens[$lineNumber][] = [ | |
'type' => -1, | |
'typeName' => 'RAW', | |
'char' => tabs_to_spaces($token), | |
]; | |
} | |
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; | |
} | |
} |