Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce MACRO_VAR_NAME_TYPE #334

Merged
merged 3 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ The `TwigCsFixer\Token\Tokenizer` transform the file into a list of tokens which

The name used in the definition of a macro function. Like `foo` in `{% macro foo() %}`.

- **TwigCsFixer\Token\Token::MACRO_VAR_NAME_TYPE**:

The name used for params of a macro function. Like `bar` in `{% macro foo(bar) %}`.

- **TwigCsFixer\Token\Token::TEST_NAME_TYPE**:

The name of a test function. Like in `{% if foo is test(bar) %}`.
Expand Down
1 change: 1 addition & 0 deletions src/Token/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ final class Token
public const FUNCTION_NAME_TYPE = 'FUNCTION_NAME_TYPE';
public const FILTER_NAME_TYPE = 'FILTER_NAME_TYPE';
public const MACRO_NAME_TYPE = 'MACRO_NAME_TYPE';
public const MACRO_VAR_NAME_TYPE = 'MACRO_VAR_NAME_TYPE';
public const TEST_NAME_TYPE = 'TEST_NAME_TYPE';
public const WHITESPACE_TYPE = 'WHITESPACE_TYPE';
public const TAB_TYPE = 'TAB_TYPE';
Expand Down
32 changes: 17 additions & 15 deletions src/Token/Tokenizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,16 @@ private function getBrackets(): array
return array_filter($this->bracketsAndTernary, static fn (Token $token): bool => '?' !== $token->getValue());
}

private function isInTernary(): bool
private function lastBracketMatch(string $value): bool
{
$lastBracket = end($this->bracketsAndTernary);

return false !== $lastBracket && '?' === $lastBracket->getValue();
return false !== $lastBracket && $value === $lastBracket->getValue();
}

private function isInTernary(): bool
{
return $this->lastBracketMatch('?');
}

/**
Expand Down Expand Up @@ -430,11 +435,8 @@ private function lexDqString(): void
*/
private function lexInterpolation(): void
{
$bracket = end($this->bracketsAndTernary);
Assert::notFalse($bracket, 'Interpolation always start with a bracket.');

if (
'#{' === $bracket->getValue()
$this->lastBracketMatch('#{')
&& 1 === preg_match(self::REGEX_INTERPOLATION_END, $this->code, $match, 0, $this->cursor)
) {
$bracket = array_pop($this->bracketsAndTernary);
Expand Down Expand Up @@ -592,8 +594,7 @@ private function lexOperator(string $operator): void
self::STATE_BLOCK !== $this->getState()
|| 'macro' !== $this->getStateParam('blockName')
) {
$bracket = end($this->bracketsAndTernary);
if (false !== $bracket && '(' === $bracket->getValue()) {
if ($this->lastBracketMatch('(')) {
// This is a named argument separator instead
$this->pushToken(Token::NAMED_ARGUMENT_SEPARATOR_TYPE, $operator);

Expand Down Expand Up @@ -640,6 +641,12 @@ private function lexName(string $name): void
&& null === $lastNonEmptyToken->getRelatedToken()
) {
$this->pushToken(Token::TEST_NAME_TYPE, $name, $lastNonEmptyToken);
} elseif (
self::STATE_BLOCK === $this->getState()
&& 'macro' === $this->getStateParam('blockName')
&& $this->lastBracketMatch('(')
) {
$this->pushToken(Token::MACRO_VAR_NAME_TYPE, $name);
} else {
$this->pushToken(Token::NAME_TYPE, $name);
}
Expand Down Expand Up @@ -699,18 +706,13 @@ private function lexPunctuation(): void

$this->pushToken(Token::PUNCTUATION_TYPE, $currentCode, $bracket);
} elseif (':' === $currentCode) {
if ([] === $this->bracketsAndTernary) {
throw CannotTokenizeException::unexpectedCharacter($currentCode, $this->line);
}

$bracket = end($this->bracketsAndTernary);
if ('[' === $bracket->getValue()) {
if ($this->lastBracketMatch('[')) {
// This is a slice shortcut '[0:1]' instead
$this->lexOperator($currentCode);

return;
}
if ('(' === $bracket->getValue()) {
if ($this->lastBracketMatch('(')) {
// This is a named argument separator instead
$this->pushToken(Token::NAMED_ARGUMENT_SEPARATOR_TYPE, $currentCode);

Expand Down
1 change: 0 additions & 1 deletion tests/Token/Tokenizer/Fixtures/invalid7.twig

This file was deleted.

2 changes: 1 addition & 1 deletion tests/Token/Tokenizer/Fixtures/test15.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
{{ foo(foo:1) }}
{{ foo({foo:1}) }}
{{ (foo==1) }}
{% macro input(name='foo') %}{{ name }}{% endmacro %}
{% macro input(name='foo', opts={foo: 1}) %}{{ name }}{% endmacro %}
33 changes: 21 additions & 12 deletions tests/Token/Tokenizer/TokenizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -753,24 +753,34 @@ public static function tokenizeDataProvider(): iterable
58 => Token::WHITESPACE_TYPE,
59 => Token::MACRO_NAME_TYPE,
60 => Token::PUNCTUATION_TYPE,
61 => Token::NAME_TYPE,
61 => Token::MACRO_VAR_NAME_TYPE,
62 => Token::OPERATOR_TYPE,
63 => Token::STRING_TYPE,
64 => Token::PUNCTUATION_TYPE,
65 => Token::WHITESPACE_TYPE,
66 => Token::BLOCK_END_TYPE,
67 => Token::VAR_START_TYPE,
68 => Token::WHITESPACE_TYPE,
66 => Token::MACRO_VAR_NAME_TYPE,
67 => Token::OPERATOR_TYPE,
68 => Token::PUNCTUATION_TYPE,
69 => Token::NAME_TYPE,
70 => Token::WHITESPACE_TYPE,
71 => Token::VAR_END_TYPE,
72 => Token::BLOCK_START_TYPE,
73 => Token::WHITESPACE_TYPE,
74 => Token::BLOCK_NAME_TYPE,
70 => Token::PUNCTUATION_TYPE,
71 => Token::WHITESPACE_TYPE,
72 => Token::NUMBER_TYPE,
73 => Token::PUNCTUATION_TYPE,
74 => Token::PUNCTUATION_TYPE,
75 => Token::WHITESPACE_TYPE,
76 => Token::BLOCK_END_TYPE,
77 => Token::EOL_TYPE,
78 => Token::EOF_TYPE,
77 => Token::VAR_START_TYPE,
78 => Token::WHITESPACE_TYPE,
79 => Token::NAME_TYPE,
80 => Token::WHITESPACE_TYPE,
81 => Token::VAR_END_TYPE,
82 => Token::BLOCK_START_TYPE,
83 => Token::WHITESPACE_TYPE,
84 => Token::BLOCK_NAME_TYPE,
85 => Token::WHITESPACE_TYPE,
86 => Token::BLOCK_END_TYPE,
87 => Token::EOL_TYPE,
88 => Token::EOF_TYPE,
],
];

Expand Down Expand Up @@ -829,6 +839,5 @@ public static function tokenizeInvalidDataProvider(): iterable
yield [__DIR__.'/Fixtures/invalid4.twig', 'Unexpected character ")" at line 1.'];
yield [__DIR__.'/Fixtures/invalid5.twig', 'Unexpected character "#" at line 1.'];
yield [__DIR__.'/Fixtures/invalid6.twig', 'Unclosed comment at line 1.'];
yield [__DIR__.'/Fixtures/invalid7.twig', 'Unexpected character ":" at line 1.'];
}
}