/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; $arrayDepth = 0; $skip = false; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === \Twig_Token::PUNCTUATION_TYPE && $token->getValue() === '(') { $skip = true; // Ignore function arguments or embedded expressions (eg. [ func(1, 2) ] ) // This prevents this rule from having influence on arguments spacing. } if ($token->getType() === \Twig_Token::PUNCTUATION_TYPE && $token->getValue() === '?') { $skip = true; } if ($token->getValue() === '[' && $token->getType() === \Twig_Token::PUNCTUATION_TYPE) { if ($tokens->look(-1)->getType() === \Twig_Token::NAME_TYPE) { break; // This is not an array declaration, but an array access ( eg. : foo[1] ) } $arrayDepth++; $skip = false; // We entered a new array or hash, from now on do not skip anything. } if ($token->getValue() === ']' && $token->getType() === \Twig_Token::PUNCTUATION_TYPE) { $arrayDepth--; } if (!$skip && $arrayDepth > 0 && $token->getType() === \Twig_Token::PUNCTUATION_TYPE && $token->getValue() === ',') { $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spaceAfter); $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spaceBefore, false); } $tokens->next(); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->reset(); $macros = []; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === \Twig_Token::NAME_TYPE && $token->getValue() === 'import') { while ($tokens->getCurrent()->getValue() !== 'as') { $tokens->next(); } $tokens->next(); while (in_array($tokens->getCurrent()->getType(), [\Twig_Token::NAME_TYPE, \Twig_Token::PUNCTUATION_TYPE, Token::WHITESPACE_TYPE])) { $next = $tokens->getCurrent(); if ($next->getType() === \Twig_Token::NAME_TYPE) { $macros[$next->getValue()] = $next; } $tokens->next(); } } elseif ($token->getType() === \Twig_Token::NAME_TYPE && array_key_exists($token->getValue(), $macros)) { unset($macros[$token->getValue()]); } $tokens->next(); } foreach ($macros as $name => $originalToken) { $this->addViolation($tokens->getFilename(), $originalToken->getLine(), $originalToken->getColumn(), sprintf('Unused macro "%s".', $name)); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; $ternaryDepth = 0; $closingTokens = []; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getValue() === '?' && $token->getType() === \Twig_Token::PUNCTUATION_TYPE) { // Memorize where is the closing ":" punctuation to validate spacing later. $closingTokens[] = $this->seekTernaryElse($tokens); $next = $tokens->look(Lexer::NEXT_TOKEN); if ($next->getValue() !== ':') { $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spacing); } $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spacing); } if (in_array($token, $closingTokens)) { $previous = $tokens->look(Lexer::PREVIOUS_TOKEN); if ($previous->getValue() !== '?') { $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spacing); } $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spacing); } $tokens->next(); } return $this->violations; }
/** * @expectedException Twig_Error_Syntax * @expectedMessage Unexpected end of template */ public function testEndOfTemplateLook() { $stream = new Twig_TokenStream(array(new Twig_Token(Twig_Token::BLOCK_START_TYPE, 1, 1))); while (!$stream->isEOF()) { $stream->look(); $stream->next(); } }
public function testNext() { $stream = new Twig_TokenStream(self::$tokens); $repr = array(); while (!$stream->isEOF()) { $token = $stream->next(); $repr[] = $token->getValue(); } $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() advances the pointer and returns the current token'); }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === \Twig_Token::PUNCTUATION_TYPE && in_array($token->getValue(), $this->punctuations)) { $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spacing); $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spacing); } $tokens->next(); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; $watchList = array_keys(self::CHECKS); while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if (in_array($token->getType(), $watchList)) { $checks = self::CHECKS[$token->getType()]; $this->assertSpacing($tokens, $checks[0], $checks[1]); } $tokens->next(); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->reset(); while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === Token::NEWLINE_TYPE && $tokens->look(-1)->getType() === Token::WHITESPACE_TYPE || $token->getType() === Token::TEXT_TYPE) { if (preg_match("/[[:blank:]]+\n/", $token->getValue())) { $this->addViolation($tokens->getFilename(), $token->getLine(), $token->getColumn(), 'A line should not end with blank space(s).'); } } $tokens->next(); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->reset(); while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === \Twig_Token::NAME_TYPE && preg_match('/[A-Z]/', $token->getValue())) { if ($tokens->look(Lexer::PREVIOUS_TOKEN)->getType() === Token::WHITESPACE_TYPE && $tokens->look(-2)->getValue() === 'set') { $this->addViolation($tokens->getFilename(), $token->getLine(), $token->getColumn(), sprintf('The "%s" variable should be in lower case (use _ as a separator).', $token->getValue())); } } $tokens->next(); } return $this->violations; }
public function testRewind() { $stream = new Twig_TokenStream(self::$tokens, '', false); $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); $stream->rewind(); $repr = array(); while (!$stream->isEOF()) { $token = $stream->next(false); $repr[] = $token->getValue(); } $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->rewind() pushes all pushed tokens to the token array'); }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === \Twig_Token::OPERATOR_TYPE && in_array($token->getValue(), $this->operators)) { // allows unary operators to be next to an opening parenthesis. if (!($this->isUnary($token->getValue()) && $tokens->look(-1)->getValue() == '(')) { $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spacing); } $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spacing); } $tokens->next(); } return $this->violations; }
/** * @param \Twig_TokenStream $stream * @param int $lineno * @param string $export_type * @return WebpackNode * @throws \Twig_Error_Syntax */ private function parseType(\Twig_TokenStream $stream, $lineno, $export_type) { $files = []; while (!$stream->isEOF() && !$stream->getCurrent()->test(\Twig_Token::BLOCK_END_TYPE)) { $asset = $stream->expect(\Twig_Token::STRING_TYPE)->getValue(); if (false === ($file = $this->extension->webpackAsset($asset)[$export_type])) { continue; } $files[] = $file; } $stream->expect(\Twig_Token::BLOCK_END_TYPE); $body = $this->parser->subparse(function ($token) { return $token->test(['end' . $this->getTag()]); }, true); $stream->expect(\Twig_Token::BLOCK_END_TYPE); return new WebpackNode([$body], ['files' => $files], $lineno, $this->getTag()); }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; $sliceOpened = false; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getValue() === '[' && $tokens->look(-1)->getType() === \Twig_Token::NAME_TYPE) { $sliceOpened = true; } if ($sliceOpened > 0 && $token->getValue() === ':') { $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spaces); $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spaces, false); } if ($token->getValue() === ']') { $sliceOpened = false; } $tokens->next(); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->reset(); $variables = []; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getType() === \Twig_Token::NAME_TYPE) { if ($tokens->look(Lexer::PREVIOUS_TOKEN)->getType() === Token::WHITESPACE_TYPE && $tokens->look(-2)->getValue() === 'set') { $variables[$token->getValue()] = $token; } else { unset($variables[$token->getValue()]); } } $tokens->next(); } foreach ($variables as $name => $originalToken) { $this->addViolation($tokens->getFilename(), $originalToken->getLine(), $originalToken->getColumn(), sprintf('Unused variable "%s".', $name)); } return $this->violations; }
/** * {@inheritdoc} */ public function check(\Twig_TokenStream $tokens) { $this->violations = []; while (!$tokens->isEOF()) { $token = $tokens->getCurrent(); if ($token->getValue() === '(' && $token->getType() === \Twig_Token::PUNCTUATION_TYPE) { $this->assertSpacing($tokens, Lexer::NEXT_TOKEN, $this->spacing); // Space allowed if previous token is not a function name. // Space also allowed in case of control structure if ($tokens->look(-2)->getType() === \Twig_Token::NAME_TYPE) { $value = $tokens->look(-2)->getValue(); $spacing = in_array($value, ['if', 'elseif', 'in']) ? $this->controlStructureSpacing : $this->spacing; $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $spacing); } } if ($token->getValue() === ')' && $token->getType() === \Twig_Token::PUNCTUATION_TYPE && $tokens->look(Lexer::PREVIOUS_TOKEN)->getType() === Token::WHITESPACE_TYPE) { $this->assertSpacing($tokens, Lexer::PREVIOUS_TOKEN, $this->spacing); } $tokens->next(); } return $this->violations; }
$repr = array(); while (!$stream->isEOF()) { $token = $stream->next(); $repr[] = $token->getValue(); } $t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->look() pushes the token to the stack'); $stream = new Twig_TokenStream($tokens, '', false); $t->is($stream->look()->getValue(), 2, '->look() returns the next token'); $t->is($stream->look()->getValue(), 3, '->look() can be called several times to look more than one upcoming token'); $t->is($stream->look()->getValue(), 4, '->look() can be called several times to look more than one upcoming token'); $t->is($stream->look()->getValue(), 5, '->look() can be called several times to look more than one upcoming token'); $repr = array(); while (!$stream->isEOF()) { $token = $stream->next(); $repr[] = $token->getValue(); } $t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->look() pushes the token to the stack'); // ->rewind() $t->diag('->rewind()'); $stream = new Twig_TokenStream($tokens, '', false); $t->is($stream->look()->getValue(), 2, '->look() returns the next token'); $t->is($stream->look()->getValue(), 3, '->look() can be called several times to look more than one upcoming token'); $t->is($stream->look()->getValue(), 4, '->look() can be called several times to look more than one upcoming token'); $t->is($stream->look()->getValue(), 5, '->look() can be called several times to look more than one upcoming token'); $stream->rewind(); $repr = array(); while (!$stream->isEOF()) { $token = $stream->next(false); $repr[] = $token->getValue(); } $t->is(implode(', ', $repr), '1, 2, 3, 4, 5, 6, 7', '->rewind() pushes all pushed tokens to the token array');
protected function getTwigArgument(\Twig_TokenStream $stream) { $buffer = ""; // 1. Move to open bracket while (!$stream->isEOF()) { if ($stream->next()->getValue() === '(') { break; } } // 2. Fetch until close bracket while (!$stream->isEOF()) { $token = $stream->next()->getValue(); if ($token === ')' || $token === ',') { break; } $buffer .= $token; } return $buffer; }