Skip to content

Commit

Permalink
Refactor InterpolationScanner and LineAnalyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekatarnls committed May 16, 2020
1 parent 87e84c2 commit e6cdbe9
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 93 deletions.
26 changes: 6 additions & 20 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
---
engines:
duplication:
enabled: true
config:
languages:
- ruby
- javascript
- python
- php
version: "2"
checks:
fixme:
enabled: true
phpmd:
enabled: true
config:
rulesets: rulesets.xml
ratings:
paths:
- "**.inc"
- "**.js"
- "**.jsx"
- "**.module"
- "**.php"
- "**.py"
- "**.rb"
similar-code:
config:
threshold: 64
exclude_patterns:
- "**/tests/**"
- "**/tests/**"
116 changes: 67 additions & 49 deletions src/Phug/Lexer/Lexer/Analyzer/LineAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,63 +68,16 @@ public function disallowInterpolation()
$this->allowedInterpolation = false;
}

protected function getLine()
{
$line = [];
$indent = $this->reader->match('[ \t]+(?=\S)') ? mb_strlen($this->reader->getMatch(0)) : INF;
if ($indent < $this->maxIndent) {
$this->maxIndent = $indent;
}

if ($this->allowedInterpolation) {
foreach ($this->state->scan(InterpolationScanner::class) as $subToken) {
$line[] = $subToken instanceof TextToken ? $subToken->getValue() : $subToken;
}
}

if (($text = $this->reader->readUntilNewLine()) !== null) {
$line[] = $text;
}

return $line;
}

protected function recordLine()
{
$this->lines[] = $this->getLine();

if ($this->newLine = $this->reader->peekNewLine()) {
$this->reader->consume(1);
}
}

public function analyze($quitOnOutdent, array $breakChars = [])
{
$this->outdent = false;
$this->level = $this->state->getLevel();
$this->newLevel = $this->level;
$breakChars = array_merge($breakChars, [' ', "\t", "\n"]);
$this->newLine = false;
$first = true;

while ($this->reader->hasLength()) {
$this->newLine = true;
$indentationScanner = new IndentationScanner();
$newLevel = $indentationScanner->getIndentLevel($this->state, $this->level);

if (!$first || $newLevel > $this->newLevel) {
$this->newLevel = $newLevel;
}

$first = false;

if (!$this->reader->peekChars($breakChars)) {
$this->outdent = $this->newLevel < $this->level;

break;
}

if ($this->newLevel < $this->level && $this->reader->match('[ \t]*\n')) {
foreach ($this->hasChunksUntil($breakChars) as $lowerLevel) {
if ($lowerLevel && $this->reader->match('[ \t]*\n')) {
$this->reader->consume(mb_strlen($this->reader->getMatch(0)));
$this->lines[] = [];

Expand Down Expand Up @@ -202,4 +155,69 @@ public function getNewLevel()
{
return $this->newLevel;
}

protected function getLineChunks()
{
$line = [];

if ($this->allowedInterpolation) {
foreach ($this->state->scan(InterpolationScanner::class) as $subToken) {
$line[] = $subToken instanceof TextToken ? $subToken->getValue() : $subToken;
}
}

if (($text = $this->reader->readUntilNewLine()) !== null) {
$line[] = $text;
}

return $line;
}

protected function getLine()
{
$indent = $this->reader->match('[ \t]+(?=\S)') ? mb_strlen($this->reader->getMatch(0)) : INF;

if ($indent < $this->maxIndent) {
$this->maxIndent = $indent;
}

return $this->getLineChunks();
}

protected function recordLine()
{
$this->lines[] = $this->getLine();

if ($this->newLine = $this->reader->peekNewLine()) {
$this->reader->consume(1);
}
}

protected function setNewLevel($newLevel, $first = false)
{
if (!$first || $newLevel > $this->newLevel) {
$this->newLevel = $newLevel;
}
}

protected function hasChunksUntil($breakChars)
{
$first = true;

while ($this->reader->hasLength()) {
$this->newLine = true;
$indentationScanner = new IndentationScanner();
$newLevel = $indentationScanner->getIndentLevel($this->state, $this->level);
$this->setNewLevel($newLevel, $first);
$first = false;

if (!$this->reader->peekChars($breakChars)) {
$this->outdent = $this->newLevel < $this->level;

break;
}

yield $this->newLevel < $this->level;
}
}
}
55 changes: 31 additions & 24 deletions src/Phug/Lexer/Lexer/Scanner/InterpolationScanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,36 @@
use Phug\Lexer\Token\TagInterpolationEndToken;
use Phug\Lexer\Token\TagInterpolationStartToken;
use Phug\Lexer\Token\TextToken;
use RuntimeException;

class InterpolationScanner implements ScannerInterface
{
protected function scanInterpolation(State $state, $tagInterpolation, $interpolation, $escape)
protected function scanTagInterpolation(State $state, $tagInterpolation)
{
if (strpos($interpolation, "\n") !== false) {
$state->throwException('End of line was reached with no closing bracket for interpolation.');
}

if ($tagInterpolation) {
/** @var TagInterpolationStartToken $start */
$start = $state->createToken(TagInterpolationStartToken::class);
/** @var TagInterpolationEndToken $end */
$end = $state->createToken(TagInterpolationEndToken::class);

$start->setEnd($end);
$end->setStart($start);
/** @var TagInterpolationStartToken $start */
$start = $state->createToken(TagInterpolationStartToken::class);
/** @var TagInterpolationEndToken $end */
$end = $state->createToken(TagInterpolationEndToken::class);

$lexer = $state->getLexer();
$start->setEnd($end);
$end->setStart($start);

yield $start;
$lexer = $state->getLexer();

foreach ($lexer->lex($tagInterpolation) as $token) {
if ($token instanceof NewLineToken) {
$state->throwException('End of line was reached with no closing bracket for interpolation.');
}
yield $start;

yield $token;
foreach ($lexer->lex($tagInterpolation) as $token) {
if ($token instanceof NewLineToken) {
$state->throwException('End of line was reached with no closing bracket for interpolation.');
}

yield $end;

return;
yield $token;
}

yield $end;
}

protected function scanExpressionInterpolation(State $state, $interpolation, $escape)
{
/** @var InterpolationStartToken $start */
$start = $state->createToken(InterpolationStartToken::class);
/** @var InterpolationEndToken $end */
Expand All @@ -72,6 +66,19 @@ protected function scanInterpolation(State $state, $tagInterpolation, $interpola
yield $end;
}

protected function scanInterpolation(State $state, $tagInterpolation, $interpolation, $escape)
{
if (strpos($interpolation, "\n") !== false) {
$state->throwException('End of line was reached with no closing bracket for interpolation.');
}

if ($tagInterpolation) {
return $this->scanTagInterpolation($state, $tagInterpolation);
}

return $this->scanExpressionInterpolation($state, $interpolation, $escape);
}

protected function needSeparationBlankLine(State $state)
{
$reader = $state->getReader();
Expand Down

0 comments on commit e6cdbe9

Please sign in to comment.